/* * Copyright 2004-2015 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.framework.container.factory; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import org.seasar.framework.container.ExternalContext; import org.seasar.framework.container.ExternalContextComponentDefRegister; import org.seasar.framework.container.S2Container; import org.seasar.framework.container.util.SmartDeployUtil; import org.seasar.framework.env.Env; import org.seasar.framework.exception.EmptyRuntimeException; import org.seasar.framework.exception.JarDuplicatedException; import org.seasar.framework.log.Logger; import org.seasar.framework.util.DisposableUtil; import org.seasar.framework.util.InputStreamUtil; /** * 唯一の{@link org.seasar.framework.container.S2Container S2コンテナ} * を提供するためのファクトリクラスです。 * <p> * シングルトンS2コンテナファクトリは、設定ファイルに基づいてS2コンテナを生成・初期化し、それを保持します。 * 保持されるS2コンテナは、このクラスをロードしたクラスローダで一意になります。 * </p> * <p> * デフォルトの設定ファイル名は<code>app.dicon</code>となります。 * </p> * <p> * シングルトンS2コンテナファクトリの標準的な利用方法としては、 アプリケーション開始時に{@link #init()}を呼び出して、 * {@link #getContainer()}でS2コンテナを取得し、 アプリケーション終了時に{@link #destroy()}を呼び出します。 * Webアプリケーションであれば * {@link javax.servlet.Servlet#init(javax.servlet.ServletConfig)}で * {@link #init()}を、 {@link javax.servlet.Servlet#destroy()}で{@link #destroy()} * を呼び出します。 * </p> * * @author koichik * @author goto */ public class SingletonS2ContainerFactory { private static final Logger logger = Logger .getLogger(SingletonS2ContainerFactory.class); private static String configPath = "app.dicon"; private static ExternalContext externalContext; private static ExternalContextComponentDefRegister externalContextComponentDefRegister; private static S2Container container; private SingletonS2ContainerFactory() { } /** * 設定ファイルのファイルパスを返します。 * * @return 設定ファイルのファイルパス */ public static String getConfigPath() { return configPath; } /** * 設定ファイルのファイルパスを設定します。 * * @param path * 設定ファイルのファイルパス */ public static void setConfigPath(String path) { configPath = path; } /** * {@link org.seasar.framework.container.ExternalContext 外部コンテキスト}を返します。 * * @return 外部コンテキスト */ public static ExternalContext getExternalContext() { return externalContext; } /** * {@link org.seasar.framework.container.ExternalContext 外部コンテキスト}を設定します。 * * @param extCtx * 外部コンテキスト */ public static void setExternalContext(ExternalContext extCtx) { externalContext = extCtx; } /** * {@link org.seasar.framework.container.ExternalContextComponentDefRegister * 外部コンテキストコンポーネント定義レジスタ}を返します。 * * @return 外部コンテキストコンポーネント定義レジスタ */ public static ExternalContextComponentDefRegister getExternalContextComponentDefRegister() { return externalContextComponentDefRegister; } /** * {@link org.seasar.framework.container.ExternalContextComponentDefRegister * 外部コンテキストコンポーネント定義レジスタ}を設定します。 * * @param extCtxComponentDefRegister * 外部コンテキストコンポーネント定義レジスタ */ public static void setExternalContextComponentDefRegister( ExternalContextComponentDefRegister extCtxComponentDefRegister) { externalContextComponentDefRegister = extCtxComponentDefRegister; } /** * 設定ファイルに基づいてS2コンテナを生成・初期化し、それを保持します。 既にS2コンテナが保持されている場合は何もしません。 * <p> * S2コンテナを生成した後、 初期化を行なう前に必要に応じて、 * 外部コンテキストおよび外部コンテキストコンポーネント定義レジスタをS2コンテナに設定します。 * </p> * * @see S2ContainerFactory#create(String) * @see org.seasar.framework.container.ExternalContext * @see org.seasar.framework.container.ExternalContextComponentDefRegister */ public static void init() { if (container != null) { return; } checkVersions(); container = S2ContainerFactory.create(configPath); if (container.getExternalContext() == null) { if (externalContext != null) { container.setExternalContext(externalContext); } } else if (container.getExternalContext().getApplication() == null && externalContext != null) { container.getExternalContext().setApplication( externalContext.getApplication()); } if (container.getExternalContextComponentDefRegister() == null && externalContextComponentDefRegister != null) { container .setExternalContextComponentDefRegister(externalContextComponentDefRegister); } container.init(); logger.info("Running on [ENV]" + Env.getValue() + ", [DEPLOY MODE]" + SmartDeployUtil.getDeployMode(container)); } /** * S2コンテナやその他の終了処理を行ないます。 */ public static void destroy() { if (container == null) { return; } container.destroy(); container = null; DisposableUtil.dispose(); } /** * 唯一のS2コンテナを返します。 S2コンテナが保持されていない場合、 * {@link org.seasar.framework.exception.EmptyRuntimeException}をスローします。 * * @return S2コンテナ */ public static S2Container getContainer() { if (container == null) { throw new EmptyRuntimeException("S2Container"); } return container; } /** * 保持するS2コンテナを設定します。 * * @param c * S2コンテナ */ public static void setContainer(S2Container c) { container = c; } /** * S2コンテナを保持しているかどうかを返します。 * * @return S2コンテナを保持している場合は<code>true</code>、そうでない場合は<code>false</code> */ public static boolean hasContainer() { return container != null; } private static void checkVersions() { checkVersion("s2-framework"); checkVersion("s2-extension"); checkVersion("s2-tiger"); } private static void checkVersion(final String artifactId) { final Map versions = getVersions(artifactId); if (versions.isEmpty()) { return; } if (versions.size() > 1) { throw new JarDuplicatedException(artifactId, versions); } final String version = (String) versions.keySet().iterator().next(); final List urlList = (List) versions.values().iterator().next(); if (urlList.size() > 1) { logger.log("WSSR0016", new Object[] { artifactId, version, urlList }); return; } logger.log("ISSR0009", new Object[] { artifactId, version }); } private static Map getVersions(final String artifactId) { final Map versions = new HashMap(); try { final String name = "META-INF/maven/org.seasar.container/" + artifactId + "/pom.properties"; final Enumeration urls = Thread.currentThread() .getContextClassLoader().getResources(name); while (urls.hasMoreElements()) { URL url = (URL) urls.nextElement(); final InputStream is = url.openStream(); try { final Properties props = new Properties(); props.load(is); String version = props.getProperty("version"); final List urlList; if (versions.containsKey(version)) { urlList = (List) versions.get(version); } else { urlList = new ArrayList(); versions.put(version, urlList); } urlList.add(url.toExternalForm()); } finally { InputStreamUtil.close(is); } } } catch (final Exception ignore) { } return versions; } }