/* * Copyright 2011, 2012 Odysseus Software GmbH * * 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.apache.synapse.commons.staxon.core.json.stream; import org.apache.synapse.commons.staxon.core.json.stream.impl.Constants; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.util.Properties; import javax.xml.stream.FactoryConfigurationError; /** * Abstract JSON stream ({@link JsonStreamSource} and {@link JsonStreamTarget}) factory. * <p/> * <p>This class provides the static {@link #newFactory()} method to lookup and instantiate a default * implementation using the Services API (as detailed in the JAR specification).</p> */ public abstract class JsonStreamFactory { private static String getMetaInfServicesClassName(Class<?> serviceInterface, ClassLoader classLoader) { String serviceId = "META-INF/services/" + serviceInterface.getName(); InputStream input = classLoader.getResourceAsStream(serviceId); if (input != null) { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); try { return reader.readLine(); } catch (IOException e) { // do nothing } finally { try { reader.close(); } catch (Exception io) { // do nothing } } } catch (IOException e) { try { input.close(); } catch (Exception io) { // do nothing } } } return null; } private static String getJavaHomeLibClassName(Class<?> serviceInterface, String bundleName) { String home = System.getProperty("java.home"); if (home != null) { InputStream input = null; String path = home + File.separator + "lib" + File.separator + bundleName + ".properties"; File file = new File(path); try { if (file.exists()) { input = new FileInputStream(file); Properties props = new Properties(); props.load(input); return props.getProperty(serviceInterface.getName()); } } catch (IOException e) { // do nothing } catch (SecurityException e) { // do nothing } finally { if (input != null) { try { input.close(); } catch (IOException io) { // do nothing } } } } return null; } /** * <p>Create a new instance of a JsonStreamFactory.</p> * <p>Determines the class to instantiate as follows: * <ol> * <li>Use the Services API (as detailed in the JAR specification). If a resource with the name * of META-INF/services/de.odysseus.staxon.json.stream.JsonStreamFactory exists, then its first line, * if present, is used as the UTF-8 encoded name of the implementation class.</li> * <li>Use the properties file "lib/staxon.properties" in the JRE directory. If this file exists * and is readable by the java.util.Properties.load(InputStream) method, and it contains an entry * whose key is "de.odysseus.staxon.json.stream.JsonStreamFactory", then the value of that entry is * used as the name of the implementation class.</li> * <li>Use the de.odysseus.staxon.json.stream.JsonStreamFactory system property. If a system property * with this name is defined, then its value is used as the name of the implementation class.</li> * <li>Use platform default: "de.odysseus.staxon.json.stream.impl.JsonStreamFactoryImpl".</li> * </ol> * </p> * * @return An instance of JsonStreamFactory. * @throws FactoryConfigurationError if a factory class cannot be found or instantiation fails. */ public static JsonStreamFactory newFactory() throws FactoryConfigurationError { ClassLoader classLoader; try { classLoader = Thread.currentThread().getContextClassLoader(); } catch (SecurityException e) { classLoader = JsonStreamFactory.class.getClassLoader(); } String className = getMetaInfServicesClassName(JsonStreamFactory.class, classLoader); if (className == null || className.trim().length() == 0) { className = getJavaHomeLibClassName(JsonStreamFactory.class, "staxon"); } if (className == null || className.trim().length() == 0) { try { className = System.getProperty(JsonStreamFactory.class.getName()); } catch (Exception se) { // do nothing } } if (className == null || className.trim().length() == 0) { className = "org.apache.synapse.commons.staxon.core.json.stream.impl.JsonStreamFactoryImpl"; } try { return (JsonStreamFactory) classLoader.loadClass(className).newInstance(); } catch (Throwable e) { throw new FactoryConfigurationError("Error creating stream factory: " + e); } } /** * Create stream source. * * @param input * @return stream source * @throws IOException */ public abstract JsonStreamSource createJsonStreamSource(InputStream input) throws IOException; /** * Create stream source. * * @param input * @param scanner JSON Scanner to use * @return stream source * @throws IOException */ public abstract JsonStreamSource createJsonStreamSource(InputStream input, Constants.SCANNER scanner) throws IOException; /** * Create stream source. * * @param reader * @return stream source * @throws IOException */ public abstract JsonStreamSource createJsonStreamSource(Reader reader) throws IOException; /** * Create stream source. * * @param reader * @param scanner JSON Scanner to use * @return stream source * @throws IOException */ public abstract JsonStreamSource createJsonStreamSource(Reader reader, Constants.SCANNER scanner) throws IOException; /** * Create stream target. * * @param output * @param pretty * @return stream target * @throws IOException */ public abstract JsonStreamTarget createJsonStreamTarget(OutputStream output, boolean pretty) throws IOException; /** * Create stream target. * * @param writer * @param pretty * @return stream target * @throws IOException */ public abstract JsonStreamTarget createJsonStreamTarget(Writer writer, boolean pretty) throws IOException; }