View Javadoc

1   /*
2    * Copyright 2004-2008 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.uruma.rcp.core;
17  
18  import java.net.URL;
19  import java.util.ArrayList;
20  import java.util.Dictionary;
21  import java.util.Hashtable;
22  import java.util.List;
23  import java.util.Properties;
24  
25  import org.eclipse.core.internal.preferences.exchange.IProductPreferencesService;
26  import org.eclipse.core.internal.preferences.legacy.ProductPreferencesService;
27  import org.eclipse.swt.widgets.Display;
28  import org.eclipse.swt.widgets.Shell;
29  import org.osgi.framework.Bundle;
30  import org.osgi.framework.BundleActivator;
31  import org.osgi.framework.BundleContext;
32  import org.osgi.framework.Constants;
33  import org.osgi.framework.ServiceReference;
34  import org.seasar.uruma.core.UrumaConstants;
35  import org.seasar.uruma.core.UrumaMessageCodes;
36  import org.seasar.uruma.exception.UrumaAppInitException;
37  import org.seasar.uruma.exception.UrumaAppNotFoundException;
38  import org.seasar.uruma.log.UrumaLogger;
39  import org.seasar.uruma.rcp.UrumaService;
40  import org.seasar.uruma.rcp.core.UrumaBundleState.BundleState;
41  import org.seasar.uruma.rcp.util.BundleInfoUtil;
42  import org.seasar.uruma.rcp.util.BundleUtil;
43  import org.seasar.uruma.ui.dialogs.UrumaErrorDialog;
44  import org.seasar.uruma.util.MessageUtil;
45  
46  /**
47   * Uruma のための {@link BundleActivator} です。<br />
48   * 
49   * @author y-komori
50   */
51  public class CoreActivator implements BundleActivator, UrumaConstants,
52          UrumaMessageCodes {
53      private static final UrumaLogger logger = UrumaLogger
54              .getLogger(CoreActivator.class);
55  
56      public void start(final BundleContext context) throws Exception {
57          logger.log(URUMA_BUNDLE_START);
58  
59          try {
60              context.addBundleListener(new UrumaBundleListener());
61  
62              List<Bundle> activated = prepareUrumaService(context);
63              if (activated.size() == 0) {
64                  throw new UrumaAppNotFoundException();
65              }
66  
67              registerProductPreferenceService(context);
68  
69              UrumaBundleState.getInstance().setUrumaBundleState(
70                      BundleState.AVAILABLE);
71          } catch (Throwable ex) {
72              Display display = new Display();
73              Shell shell = new Shell(display);
74              String msg = MessageUtil.getMessageWithBundleName(
75                      URUMA_MESSAGE_BASE, "RCP_START_FAILED");
76              UrumaErrorDialog dialog = new UrumaErrorDialog(shell, "Uruma", msg,
77                      ex);
78              dialog.open();
79              shell.dispose();
80              display.dispose();
81          }
82      }
83  
84      public void stop(final BundleContext context) throws Exception {
85          UrumaBundleState.getInstance().setUrumaBundleState(
86                  BundleState.NOT_AVAILABLE);
87          logger.log(URUMA_BUNDLE_STOP);
88      }
89  
90      /**
91       * Uruma アプリケーションを検索し、アクティベートします。<br />
92       * 
93       * @param context
94       *            Uruma の {@link BundleContext}
95       * @return アクティベートに成功した Uruma アプリケーションバンドルのリスト
96       */
97      @SuppressWarnings("unchecked")
98      protected List<Bundle> prepareUrumaService(final BundleContext context) {
99          List<Bundle> successedBundleList = new ArrayList<Bundle>();
100         String serviceName = UrumaService.class.getName();
101         List<Bundle> appBundles = findUrumaApplications(context);
102         if (appBundles.size() == 0) {
103             throw new UrumaAppNotFoundException();
104         }
105 
106         Dictionary props = new Properties();
107         props.put(URUMA_SERVICE_PROP_APPS, getBundleSymbolicNames(appBundles));
108 
109         UrumaServiceFactory factory = new UrumaServiceFactory();
110         context.registerService(serviceName, factory, props);
111 
112         // Urumaアプリケーションのバンドルに対応する UrumaService を取得することで、
113         // Urumaアプリケーションをアクティベートする
114         // @see UrumaServiceFactory
115         // @see UrumaServiceImpl#initialize()
116         for (Bundle bundle : appBundles) {
117             setupLog4jConfig(bundle);
118             BundleContext appContext = bundle.getBundleContext();
119             if (appContext == null) {
120                 logger.log(INVALID_URUMA_APP_BUNDLE, bundle.getSymbolicName(),
121                         BundleUtil.getBundleState(bundle));
122                 continue;
123             }
124             ServiceReference ref = appContext
125                     .getServiceReference(UrumaService.class.getName());
126             UrumaServiceImpl service = (UrumaServiceImpl) appContext
127                     .getService(ref);
128             if (service != null
129                     && UrumaBundleState.getInstance().getAppBundleState() == BundleState.AVAILABLE) {
130                 service.registerExtensions();
131                 successedBundleList.add(bundle);
132             } else {
133                 Throwable ex = UrumaBundleState.getInstance()
134                         .getUrumaAppInitializingException();
135                 throw new UrumaAppInitException(bundle, ex, ex.getMessage());
136             }
137         }
138         return successedBundleList;
139     }
140 
141     /**
142      * インストールされているバンドルから Uruma に依存しているバンドルを探して登録します。
143      * 
144      * @param context
145      *            {@link BundleContext} オブジェクト
146      * @return Urumaアプリケーションバンドルのリスト
147      */
148     protected List<Bundle> findUrumaApplications(final BundleContext context) {
149         Bundle[] bundles = context.getBundles();
150         List<Bundle> appBundles = new ArrayList<Bundle>();
151         for (Bundle bundle : bundles) {
152             if (isUrumaApplication(bundle)) {
153                 logger.log(URUMA_APPLICATION_FOUND, bundle.getSymbolicName());
154                 appBundles.add(bundle);
155             }
156         }
157         return appBundles;
158     }
159 
160     @SuppressWarnings("unchecked")
161     protected boolean isUrumaApplication(final Bundle bundle) {
162         logger.log(ANALYZING_BUNDLE, bundle.getSymbolicName());
163         String require = BundleInfoUtil.getHeader(bundle,
164                 BundleInfoUtil.REQUIRE_BUNDLE);
165         if (require != null) {
166             if (require.indexOf(URUMA_BUNDLE_SYMBOLIC_NAME) > 0) {
167                 return true;
168             }
169         }
170         return false;
171     }
172 
173     protected String[] getBundleSymbolicNames(final List<Bundle> bundles) {
174         String[] names = new String[bundles.size()];
175         for (int i = 0; i < bundles.size(); i++) {
176             names[i] = bundles.get(i).getSymbolicName();
177         }
178         return names;
179     }
180 
181     protected void setupLog4jConfig(final Bundle bundle) {
182         URL xmlConfig = bundle.getResource(DEFAULT_LOG_XML);
183         if (xmlConfig != null) {
184             logger.addXmlConfig(xmlConfig);
185         } else {
186             URL propConfig = bundle.getResource(DEFAULT_LOG_PROPERTIES);
187             if (propConfig != null) {
188                 logger.addPropertyConfig(propConfig);
189             }
190         }
191     }
192 
193     /**
194      * {@link UrumaPreferencesService} を {@link IProductPreferencesService}
195      * としてサービス登録します。<br />
196      * {@link Constants#SERVICE_RANKING} プロパティを 1 に設定することで、 Eclipse の提供する
197      * {@link ProductPreferencesService} クラスよりも高い優先度で使用されるようにしています。
198      * 
199      * @param context
200      *            {@link BundleContext} オブジェクト
201      */
202     protected void registerProductPreferenceService(final BundleContext context) {
203         IProductPreferencesService service = new UrumaPreferencesService();
204         Dictionary<String, Integer> prop = new Hashtable<String, Integer>();
205         prop.put(Constants.SERVICE_RANKING, 1);
206         context.registerService(IProductPreferencesService.class.getName(),
207                 service, prop);
208     }
209 }