/* * © Copyright IBM Corp. 2012-2013 * * 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 com.ibm.commons; import java.io.File; import java.io.InputStream; import java.io.PrintStream; import java.util.HashMap; import java.util.List; import java.util.Properties; import com.ibm.commons.extension.ExtensionManager; import com.ibm.commons.log.LogMgrFactory; import com.ibm.commons.platform.GenericEclipsePlatform; import com.ibm.commons.platform.GenericPlatform; import com.ibm.commons.platform.GenericWebAppServerPlatform; import com.ibm.commons.platform.IPlatformFactory; import com.ibm.commons.util.StringUtil; import com.ibm.commons.util.io.StreamUtil; /** * Access to platform specific services. * <p> * There is one platform object (singleton) for the JVM. It encapsulate the services for the * underlying platform. * This platform object is automatically instantiated when necessary. * </p> * @ibm-api */ public abstract class Platform { private static Platform instance; //singleton // static { // instance = createPlatform(); // instance.initialize(); // //System.out.println("Platform: '" + instance.getName() + "'"); // $NON-NLS-1$ // } /** * Return the platform singleton. * @return the Platform singleton * @ibm-api */ public static Platform getInstance() { if(instance == null) { synchronized (Platform.class) { if(instance == null) { instance = createPlatform(); instance.initialize(); //System.out.println("Platform: '" + instance.getName() + "'"); // $NON-NLS-1$ } } } return instance; } // -------------------------------------------------------------------- public static final String FACTORY_CLASS = "com.ibm.commons.platform.Factory"; // $NON-NLS-1$ // Server side platform classes public static final String PORTAL6_PLATFORM_CLASS = "com.ibm.xsp.portlet.platform.PortalPlatform"; // $NON-NLS-1$ // public static final String TOMCAT_PLATFORM_CLASS = "com.ibm.xfaces.platform.TomcatPlatform"; // $NON-NLS-1$ // public static final String WASCE_PLATFORM_CLASS = "com.ibm.xfaces.platform.WasCEPlatform"; // $NON-NLS-1$ // Entry if needed is the System properties public static final String PLATFORM_PROPERTY_KEY = "com.ibm.commons.platform"; // $NON-NLS-1$ // Properties file storing meta info private static final String PLATFORM_PROPERTIES = "META-INF/com.ibm.commons.Platform.properties"; // $NON-NLS-1$ // In order to force the platform in some specific cases // Must be called before the first access to the platform public static void initPlatform(Platform platform) { synchronized (Platform.class) { if(instance!=null) { throw new IllegalStateException("Platform Object has already been set"); // $NON-NLS-1$ } instance = platform; instance.initialize(); //System.out.println("Platform forced to: '" + instance.getName() + "'"); // $NLS-Platform.Platform-1$ } } private static Platform createPlatform() { // 1- Use the property to find the Platform String prop = System.getProperty(PLATFORM_PROPERTY_KEY); if(StringUtil.isNotEmpty(prop)) { Platform platform = loadPlatform(prop); if(platform!=null) { return platform; } } // 2- Use an extension point try { List<Object> l = ExtensionManager.findServices(null, Platform.class, FACTORY_CLASS); if(l.size()>0) { // Only get the first one... try { IPlatformFactory factory = (IPlatformFactory)l.get(0); return factory.createPlatform(); } catch(Throwable e) { e.printStackTrace(); } } } catch(Throwable e) { // Not found... } // 2+- Try to find a factory with fixed name // This is left temporally as it won't be in use when the Domino server will be restructured try { Class<?> factoryClass = Class.forName(FACTORY_CLASS); // $NON-NLS-1$ try { IPlatformFactory factory = (IPlatformFactory)factoryClass.newInstance(); return factory.createPlatform(); } catch(Throwable e) { e.printStackTrace(); } } catch(Throwable e) { // Not found... } // 3- Try to discover it Platform platform = findPlatform(); if(platform!=null) { return platform; } // 3- Default to a generic one return new GenericPlatform(); } private LogMgrFactory logMgrFactory; private HashMap<String,Object> _objects; private HashMap<String,IPlatformService> _services; /** * */ protected Platform() { instance = this; // Ensure this is defined as the current one this._objects = new HashMap<String, Object>(); this._services = new HashMap<String, IPlatformService>(); logMgrFactory = createLogMgrFactory(); } protected void initialize() { } // protected void initLog() { // BasicConsoleHandler handler = new BasicConsoleHandler(); // handler.setLevel(Level.INFO); // Logger.getLogger("").addHandler(handler); // } /** * Return the name of the platform. * @return the platform name * @ibm-api */ public abstract String getName(); /** * Get the Log manager factory used for this platform. * @return LogMgrFactory * @ibm-api */ public final LogMgrFactory getLogMgrFactory() { return logMgrFactory; } protected abstract LogMgrFactory createLogMgrFactory(); /** * Get the output stream for this platform. * @return PrintStream * @ibm-api */ public abstract PrintStream getOutputStream(); /** * Get the error stream for this platform. * @return PrintStream * @ibm-api */ public abstract PrintStream getErrorStream(); /** * Check if the runtime platform is Eclipse based. * @return true if the host is Eclipse * @ibm-api */ public abstract boolean isEclipseBased(); /** * Check if it is a particular platform. * @return true if the platform matches the name * @ibm-api */ public boolean isPlatform(String name) { return false; } /** * Return a sevice implementation giving its name. * @param serviceId : unique id representing the platform service * @return the service implementation * @ibm-not-published */ public IPlatformService getPlatformService( String serviceId ){ return (IPlatformService)_services.get(serviceId); } /** * Register a platform service. * @param serviceId unique id * @param platformService * @ibm-not-published */ public void registerPlatformService( String serviceId, IPlatformService platformService ){ _services.put( serviceId, platformService ); } /** * Get a platform property. * @param key the property name * @return the property value * @ibm-api */ public String getProperty(String key) { String s = (String)_objects.get(key); if(s!=null) { return s; } // try { // return System.getProperty(key); // } catch(Throwable t) { // } return null; } /** * Set a platform property. * @param key the property name * @param object the new property value * @ibm-api */ public void putProperty(String key, String object) { _objects.put(key,object); } /** * Remove a platform property. * @param key the property name * @ibm-api */ public void removeProperty(String key) { _objects.remove(key); } /** * Get a global resource file as an input stream. * @return the input stream, or null if the resource is not available * @ibm-api */ public InputStream getGlobalResource(String resourceName) { return null; } /** * Get a global resource as a file. * This returns a file object when the resource is an actual file. This allows * an application to get the lastModificationDate as well as the file length * when needed. If the resource is not backed by a file, it return null. * @param resourceName * @return the corresponding file, if exists * @ibm-api */ public File getGlobalResourceFile(String resourceName) { return null; } /** * Get an object cached by the platform. * @return Object * @ibm-api */ public Object getObject(String key) { return null; } // =================================================================================== // Platform logger // This is used to log exceptions in the xpages trace file // =================================================================================== /** * Log an exception. * <p> * Note that the log not only goes to default output stream, but it can also * go a to log file if implemented by the platform. * </p> * @ibm-api */ public void log(Throwable ex) { ex.printStackTrace(); } /** * Log a message. * <p> * Note that the log not only goes to default output stream, but it can also * go a to log file if implemented by the platform. * </p> * @ibm-api */ public void log(String message) { System.out.println(message); } /** * Log a message after formatting it. * <p> * Note that the log not only goes to default output stream, but it can also * go a to log file if implemented by the platform. * </p> * @ibm-api */ public void log(String message, Object... parameters) { System.out.println(StringUtil.format(message, parameters)); } // =================================================================================== // Platform finder. // // This code is finding the current running platform, whenever it is Eclipse based // or a web app server. // =================================================================================== private static Platform findPlatform() { // PHI: // We look for the app server first as Portal may already contains the eclipse // extension point classes. On another hand, com.ibm.commons doesn't have the // J2EE classes in its class path when running inside Eclipse, so it is safe. // But we want to detect it BEFORE the Eclipse platform. //----------------------------------------------------------------------------------- // 1- Look if we are in a well know application server // We do that by looking at either global properties or available classes if( tryClass("javax.servlet.Servlet") ) { // $NON-NLS-1$ // 1. Check for a properties file META-INF // This allows third parties to create their own platform here Platform p = loadPlatformFromPropertiesFile(); if(p!=null) { return p; } // 1. Check for a portal environment if( tryClass("javax.portlet.Portlet") ) { // $NON-NLS-1$ // Check for Portal 6 if( tryClass("com.ibm.wps.datastore.domains.DatabaseDomain") ) { // $NON-NLS-1$ return loadPlatform(PORTAL6_PLATFORM_CLASS); } } // 2. Check WebSphere // TODO... // // 3. Check TOMCAT // String catalinaHome = System.getProperty("catalina.home"); // $NON-NLS-1$ // if( StringUtil.isNotEmpty(catalinaHome) ) { // return loadPlatform(TOMCAT_PLATFORM_CLASS); // } // // // 4. Check WAS-CE // // TODO... // Generic WebAppServer return new GenericWebAppServerPlatform(); } //----------------------------------------------------------------------------------- // 2- look if we are executing in an Eclipse environment // If so, use an extension point to get the actual registered platform if( tryClass("org.eclipse.core.runtime.Platform") ) { // $NON-NLS-1$ // We do a dynamic class loading to ensure that there is no hard-links to the class try { Class<?> c = Class.forName("com.ibm.commons.platform.EclipsePlatformFactory"); // $NON-NLS-1$ IPlatformFactory factory = (IPlatformFactory)c.newInstance(); return factory.createPlatform(); } catch(Throwable e) { e.printStackTrace(); } // Generic Eclipse return new GenericEclipsePlatform(); } // no luck! // The platform is unknown return null; } // Load a platform from a properties file private static Platform loadPlatformFromPropertiesFile() { try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); if(loader==null) { loader = Platform.class.getClassLoader(); } InputStream is = null; try { is = loader.getResourceAsStream(PLATFORM_PROPERTIES); if(is!=null) { Properties props = new Properties(); props.load(is); String className = props.getProperty(PLATFORM_PROPERTY_KEY); if(StringUtil.isEmpty(className)) { return loadPlatform(className); } } } finally { StreamUtil.close(is); } } catch(Throwable ex) {} return null; } // Check if a class exists in the class path private static boolean tryClass(String className) { try { Class.forName(className); return true; } catch (Throwable e) {} return false; } // Load a Platform object from the class path private static Platform loadPlatform(String className) { try { Class<?> clazz = Class.forName(className); return (Platform)clazz.newInstance(); } catch (Throwable e) {} return null; } public abstract boolean isFeatureEnabled (String featureId); }