/* * Copyright 2008 the original author or authors. * Copyright 2005 Sun Microsystems, Inc. * * 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.rioproject.impl.opstring; import org.rioproject.config.Constants; import org.rioproject.opstring.OperationalString; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.util.List; /** * The {@code OpStringLoader} utility is a helper class used to parse and return an {@link org.rioproject.opstring.OperationalString}.<br/> * This class searches in the given classloader for a resource named * <tt>/org/rioproject/opstring/OpStringParserSelectionStrategy</tt> in the classpath. * If found the content of that resource is used to indicate the name of the class * to use as an {@link OpStringParserSelectionStrategy}. * * @author Dennis Reedy * @author Jerome Bernard */ @SuppressWarnings("unused") public class OpStringLoader { private ClassLoader loader; private String[] groups; /** Path location of an OperationalString loaded from the file system */ private String loadPath; /** Default FaultDetectionHandler */ public static final String DEFAULT_FDH = "org.rioproject.impl.fdh.AdminFaultDetectionHandler"; private static final String OPSTRING_PARSER_SELECTION_STRATEGY_LOCATION = "META-INF/org/rioproject/opstring/OpStringParserSelectionStrategy"; /** * Simple constructor that creates an {@code OpStringLoader} */ public OpStringLoader() { this(null); } /** * Create a new OpStringLoader, validating documents as they are parsed. * * @param loader The parent ClassLoader to use for delegation */ public OpStringLoader(ClassLoader loader) { this.loader = loader; String group = System.getProperty(Constants.GROUPS_PROPERTY_NAME); if (group != null) this.groups = new String[]{group}; } /** * Set the default groups to add into the parsed OperationalString. * * @param groups The groups to set, must not be null * * @throws IllegalArgumentException if the groups parameter is null or * if the groups parameter is a zero-length array */ public void setDefaultGroups(String... groups) { if(groups==null) throw new IllegalArgumentException("groups is null"); if(groups.length == 0) throw new IllegalArgumentException("groups is empty"); this.groups = new String[groups.length]; System.arraycopy(groups, 0, this.groups, 0, groups.length); } /** * Parse on OperationalString from a File * * @param file A File object for a groovy file * @return An array of OperationalString objects parsed from the file. * * @throws Exception if any errors occur parsing the document */ public OperationalString[] parseOperationalString(File file) throws Exception { if (loadPath == null) { String path = file.getCanonicalPath(); int index = path.lastIndexOf(System.getProperty("file.separator")); loadPath = path.substring(0, index + 1); } return parse(file); } /** * Parse on OperationalString from a URL location. * * @param url URL location of the OperationalString * @return An array of OperationalString objects * parsed from the document loaded from the URL. * * @throws Exception if any errors occur parsing the document */ public OperationalString[] parseOperationalString(URL url) throws Exception { if(url==null) throw new IllegalArgumentException("url is null"); if (loadPath == null) { String path = url.toExternalForm(); int index = path.lastIndexOf('/'); loadPath = path.substring(0, index + 1); } return parse(url); } @SuppressWarnings("unchecked") private OperationalString[] parse(Object source) throws Exception { /* Search for a resource named * "/org/rioproject/opstring/OpStringParserSelectionStrategy" in the * classpath. * * If found read that resource and use the line of the resource as the * name of the class to use for selecting the {@link OpStringParser} * based on the source object. */ OpStringParserSelectionStrategy selectionStrategy = new DefaultOpStringParserSelectionStrategy(); ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (loader != null) cl = loader; URL propFile = cl.getResource(OPSTRING_PARSER_SELECTION_STRATEGY_LOCATION); if (propFile != null) { String strategyClassName; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(propFile.openStream())); strategyClassName = reader.readLine(); } finally { if (reader != null) reader.close(); } Class<OpStringParserSelectionStrategy> strategyClass = (Class<OpStringParserSelectionStrategy>) cl.loadClass(strategyClassName); selectionStrategy = strategyClass.newInstance(); } OpStringParser parser = selectionStrategy.findParser(source); /* If the parser has an init method, invoke it. This will * allow any previously cached results to be cleared */ try { Method init = parser.getClass().getMethod("init"); init.invoke(parser); } catch (Exception e) { //ignore } // parse the source List<OpString> opstrings = parser.parse(source, loader, groups, loadPath); return opstrings.toArray(new OperationalString[opstrings.size()]); } /** * Parse on OperationalString from a String location. * * @param location String location of the file. The parameter * passed in can either point to an URL (prefixed by http) or a file found * in the classpath. * @return An array of OperationalString objects * parsed from an XML document loaded from the location. * * @throws Exception if any errors occur parsing the document */ private OperationalString[] parseOperationalString(String location) throws Exception { if(location==null) throw new IllegalArgumentException("location is null"); URL url = getURL(location); if (url == null) throw new FileNotFoundException("OperationalString Location ["+location+"] not found"); return parseOperationalString(url); } /** * Get the URL from a file or http connection * * @param location The location string * * @return A URL * * @throws MalformedURLException If the location string is bogus */ private URL getURL(String location) throws MalformedURLException { URL url; if(location.startsWith("http") || location.startsWith("file:")) { url = new URL(location); } else { url = new File(location).toURI().toURL(); } return(url); } }