You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2017/09/08 15:15:14 UTC
[21/24] knox git commit: Merge branch 'master' into
KNOX-998-Package_Restructuring
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-server/src/main/java/org/apache/knox/gateway/deploy/impl/ServiceDefinitionDeploymentContributor.java
----------------------------------------------------------------------
diff --cc gateway-server/src/main/java/org/apache/knox/gateway/deploy/impl/ServiceDefinitionDeploymentContributor.java
index 9ac71bd,0000000..a056ac7
mode 100644,000000..100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/deploy/impl/ServiceDefinitionDeploymentContributor.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/deploy/impl/ServiceDefinitionDeploymentContributor.java
@@@ -1,256 -1,0 +1,256 @@@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.knox.gateway.deploy.impl;
+
+import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
+import org.apache.knox.gateway.deploy.DeploymentContext;
+import org.apache.knox.gateway.deploy.ServiceDeploymentContributorBase;
+import org.apache.knox.gateway.descriptor.FilterDescriptor;
+import org.apache.knox.gateway.descriptor.FilterParamDescriptor;
+import org.apache.knox.gateway.descriptor.ResourceDescriptor;
+import org.apache.knox.gateway.dispatch.GatewayDispatchFilter;
+import org.apache.knox.gateway.filter.XForwardedHeaderFilter;
+import org.apache.knox.gateway.filter.rewrite.api.CookieScopeServletFilter;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteRulesDescriptor;
+import org.apache.knox.gateway.service.definition.CustomDispatch;
+import org.apache.knox.gateway.service.definition.Policy;
+import org.apache.knox.gateway.service.definition.Rewrite;
+import org.apache.knox.gateway.service.definition.Route;
+import org.apache.knox.gateway.service.definition.ServiceDefinition;
+import org.apache.knox.gateway.topology.Provider;
+import org.apache.knox.gateway.topology.Service;
+import org.apache.knox.gateway.topology.Version;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ServiceDefinitionDeploymentContributor extends ServiceDeploymentContributorBase {
+
+ private static final String DISPATCH_ROLE = "dispatch";
+
+ private static final String DISPATCH_IMPL_PARAM = "dispatch-impl";
+
+ private static final String HTTP_CLIENT_FACTORY_PARAM = "httpClientFactory";
+
+ private static final String SERVICE_ROLE_PARAM = "serviceRole";
+
+ private static final String XFORWARDED_FILTER_NAME = "XForwardedHeaderFilter";
+
+ private static final String XFORWARDED_FILTER_ROLE = "xforwardedheaders";
+
+ private static final String DEFAULT_HA_DISPATCH_CLASS = "org.apache.knox.gateway.ha.dispatch.DefaultHaDispatch";
+
+ private static final String COOKIE_SCOPING_FILTER_NAME = "CookieScopeServletFilter";
+
+ private static final String COOKIE_SCOPING_FILTER_ROLE = "cookiescopef";
+
+ private ServiceDefinition serviceDefinition;
+
+ private UrlRewriteRulesDescriptor serviceRules;
+
+ public ServiceDefinitionDeploymentContributor(ServiceDefinition serviceDefinition, UrlRewriteRulesDescriptor serviceRules) {
+ this.serviceDefinition = serviceDefinition;
+ this.serviceRules = serviceRules;
+ }
+
+ @Override
+ public String getRole() {
+ return serviceDefinition.getRole();
+ }
+
+ @Override
+ public String getName() {
+ return serviceDefinition.getName();
+ }
+
+ @Override
+ public Version getVersion() {
+ return new Version(serviceDefinition.getVersion());
+ }
+
+ @Override
+ public void contributeService(DeploymentContext context, Service service) throws Exception {
+ contributeRewriteRules(context, service);
+ contributeResources(context, service);
+ }
+
+ private void contributeRewriteRules(DeploymentContext context, Service service) {
+ if ( serviceRules != null ) {
+ UrlRewriteRulesDescriptor clusterRules = context.getDescriptor("rewrite");
+ clusterRules.addRules(serviceRules);
+ }
+ }
+
+ private void contributeResources(DeploymentContext context, Service service) {
+ Map<String, String> filterParams = new HashMap<>();
+ List<Route> bindings = serviceDefinition.getRoutes();
+ for ( Route binding : bindings ) {
+ List<Rewrite> filters = binding.getRewrites();
+ if ( filters != null && !filters.isEmpty() ) {
+ filterParams.clear();
+ for ( Rewrite filter : filters ) {
+ filterParams.put(filter.getTo(), filter.getApply());
+ }
+ }
+ try {
+ contributeResource(context, service, binding, filterParams);
+ } catch ( URISyntaxException e ) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ private void contributeResource(DeploymentContext context, Service service, Route binding, Map<String, String> filterParams) throws URISyntaxException {
+ List<FilterParamDescriptor> params = new ArrayList<FilterParamDescriptor>();
+ ResourceDescriptor resource = context.getGatewayDescriptor().addResource();
+ resource.role(service.getRole());
+ resource.pattern(binding.getPath());
+ //add x-forwarded filter if enabled in config
+ if (context.getGatewayConfig().isXForwardedEnabled()) {
+ resource.addFilter().name(XFORWARDED_FILTER_NAME).role(XFORWARDED_FILTER_ROLE).impl(XForwardedHeaderFilter.class);
+ }
+ if (context.getGatewayConfig().isCookieScopingToPathEnabled()) {
+ FilterDescriptor filter = resource.addFilter().name(COOKIE_SCOPING_FILTER_NAME).role(COOKIE_SCOPING_FILTER_ROLE).impl(CookieScopeServletFilter.class);
+ filter.param().name(GatewayConfigImpl.HTTP_PATH).value(context.getGatewayConfig().getGatewayPath());
+ }
+ List<Policy> policyBindings = binding.getPolicies();
+ if ( policyBindings == null ) {
+ policyBindings = serviceDefinition.getPolicies();
+ }
+ if ( policyBindings == null ) {
+ //add default set
+ addDefaultPolicies(context, service, filterParams, params, resource);
+ } else {
+ addPolicies(context, service, filterParams, params, resource, policyBindings);
+ }
+ addDispatchFilter(context, service, resource, binding);
+ }
+
+ private void addPolicies(DeploymentContext context, Service service, Map<String, String> filterParams, List<FilterParamDescriptor> params, ResourceDescriptor resource, List<Policy> policyBindings) throws URISyntaxException {
+ for ( Policy policyBinding : policyBindings ) {
+ String role = policyBinding.getRole();
+ if ( role == null ) {
+ throw new IllegalArgumentException("Policy defined has no role for service " + service.getName());
+ }
+ role = role.trim().toLowerCase();
- if ( role.equals("rewrite") ) {
++ if ( "rewrite".equals(role) ) {
+ addRewriteFilter(context, service, filterParams, params, resource);
+ } else if ( topologyContainsProviderType(context, role) ) {
+ context.contributeFilter(service, resource, role, policyBinding.getName(), null);
+ }
+ }
+ }
+
+ private void addDefaultPolicies(DeploymentContext context, Service service, Map<String, String> filterParams, List<FilterParamDescriptor> params, ResourceDescriptor resource) throws URISyntaxException {
+ addWebAppSecFilters(context, service, resource);
+ addAuthenticationFilter(context, service, resource);
+ addRewriteFilter(context, service, filterParams, params, resource);
+ addIdentityAssertionFilter(context, service, resource);
+ addAuthorizationFilter(context, service, resource);
+ }
+
+ private void addRewriteFilter(DeploymentContext context, Service service, Map<String, String> filterParams, List<FilterParamDescriptor> params, ResourceDescriptor resource) throws URISyntaxException {
+ if ( !filterParams.isEmpty() ) {
+ for ( Map.Entry<String, String> filterParam : filterParams.entrySet() ) {
+ params.add(resource.createFilterParam().name(filterParam.getKey()).value(filterParam.getValue()));
+ }
+ }
+ addRewriteFilter(context, service, resource, params);
+ }
+
+ private void addDispatchFilter(DeploymentContext context, Service service, ResourceDescriptor resource, Route binding) {
+ CustomDispatch customDispatch = binding.getDispatch();
+ if ( customDispatch == null ) {
+ customDispatch = serviceDefinition.getDispatch();
+ }
+ boolean isHaEnabled = isHaEnabled(context);
+ if ( customDispatch != null ) {
+ String haContributorName = customDispatch.getHaContributorName();
+ String haClassName = customDispatch.getHaClassName();
+ String httpClientFactory = customDispatch.getHttpClientFactory();
+ if ( isHaEnabled) {
+ if (haContributorName != null) {
+ addDispatchFilter(context, service, resource, DISPATCH_ROLE, haContributorName);
+ } else if (haClassName != null) {
+ addDispatchFilterForClass(context, service, resource, haClassName, httpClientFactory);
+ } else {
+ addDefaultHaDispatchFilter(context, service, resource);
+ }
+ } else {
+ String contributorName = customDispatch.getContributorName();
+ if ( contributorName != null ) {
+ addDispatchFilter(context, service, resource, DISPATCH_ROLE, contributorName);
+ } else {
+ String className = customDispatch.getClassName();
+ if ( className != null ) {
+ addDispatchFilterForClass(context, service, resource, className, httpClientFactory);
+ } else {
+ //final fallback to the default dispatch
+ addDispatchFilter(context, service, resource, DISPATCH_ROLE, "http-client");
+ }
+ }
+ }
+ } else if (isHaEnabled) {
+ addDefaultHaDispatchFilter(context, service, resource);
+ } else {
+ addDispatchFilter(context, service, resource, DISPATCH_ROLE, "http-client");
+ }
+ }
+
+ private void addDefaultHaDispatchFilter(DeploymentContext context, Service service, ResourceDescriptor resource) {
+ FilterDescriptor filter = addDispatchFilterForClass(context, service, resource, DEFAULT_HA_DISPATCH_CLASS, null);
+ filter.param().name(SERVICE_ROLE_PARAM).value(service.getRole());
+ }
+
+ private FilterDescriptor addDispatchFilterForClass(DeploymentContext context, Service service, ResourceDescriptor resource, String dispatchClass, String httpClientFactory) {
+ FilterDescriptor filter = resource.addFilter().name(getName()).role(DISPATCH_ROLE).impl(GatewayDispatchFilter.class);
+ filter.param().name(DISPATCH_IMPL_PARAM).value(dispatchClass);
+ if (httpClientFactory != null) {
+ filter.param().name(HTTP_CLIENT_FACTORY_PARAM).value(httpClientFactory);
+ }
+ for ( Map.Entry<String, String> serviceParam : service.getParams().entrySet() ) {
+ filter.param().name(serviceParam.getKey()).value(serviceParam.getValue());
+ }
+ if ( context.getGatewayConfig().isHadoopKerberosSecured() ) {
+ filter.param().name("kerberos").value("true");
+ } else {
+ //TODO: [sumit] Get rid of special case. Add config/param capabilities to service definitions?
+ //special case for hive
+ filter.param().name("basicAuthPreemptive").value("true");
+ }
+ return filter;
+ }
+
+ private boolean isHaEnabled(DeploymentContext context) {
+ Provider provider = getProviderByRole(context, "ha");
+ if ( provider != null && provider.isEnabled() ) {
+ Map<String, String> params = provider.getParams();
+ if ( params != null ) {
+ if ( params.containsKey(getRole()) ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-server/src/main/java/org/apache/knox/gateway/dispatch/UrlConnectionDispatch.java
----------------------------------------------------------------------
diff --cc gateway-server/src/main/java/org/apache/knox/gateway/dispatch/UrlConnectionDispatch.java
index 0aa0063,0000000..ff40983
mode 100644,000000..100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/dispatch/UrlConnectionDispatch.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/dispatch/UrlConnectionDispatch.java
@@@ -1,163 -1,0 +1,163 @@@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.knox.gateway.dispatch;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.knox.gateway.GatewayMessages;
+import org.apache.knox.gateway.GatewayResources;
+import org.apache.knox.gateway.audit.api.Action;
+import org.apache.knox.gateway.audit.api.ActionOutcome;
+import org.apache.knox.gateway.audit.api.AuditServiceFactory;
+import org.apache.knox.gateway.audit.api.Auditor;
+import org.apache.knox.gateway.audit.api.ResourceType;
+import org.apache.knox.gateway.audit.log4j.audit.AuditConstants;
+import org.apache.knox.gateway.filter.AbstractGatewayFilter;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.i18n.resources.ResourcesFactory;
+import org.apache.knox.gateway.util.urltemplate.Parser;
+import org.apache.knox.gateway.util.urltemplate.Resolver;
+import org.apache.knox.gateway.util.urltemplate.Rewriter;
+import org.apache.knox.gateway.util.urltemplate.Template;
+import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
+import org.apache.hadoop.security.authentication.client.AuthenticationException;
+import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Enumeration;
+
+/**
+ *
+ */
+public class UrlConnectionDispatch extends AbstractGatewayFilter {
+
+ private static final GatewayMessages LOG = MessagesFactory.get( GatewayMessages.class );
+ private static final GatewayResources RES = ResourcesFactory.get( GatewayResources.class );
+ private static Auditor auditor = AuditServiceFactory.getAuditService().getAuditor( AuditConstants.DEFAULT_AUDITOR_NAME,
+ AuditConstants.KNOX_SERVICE_NAME, AuditConstants.KNOX_COMPONENT_NAME );
+
+ @Override
+ protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+ String method = request.getMethod().toUpperCase();
- if (method.equals("GET")) {
++ if ("GET".equals(method)) {
+ try {
+ doGet(getDispatchUrl(request), request, response);
+ } catch ( URISyntaxException e ) {
+ throw new ServletException(e);
+ }
+ } else {
+ response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+ }
+ }
+
+ protected static URI getDispatchUrl(HttpServletRequest request) {
+ StringBuffer str = request.getRequestURL();
+ String query = request.getQueryString();
+ if ( query != null ) {
+ str.append('?');
+ str.append(query);
+ }
+ URI url = URI.create(str.toString());
+ return url;
+ }
+
+ public void doGet( URI url, HttpServletRequest request, HttpServletResponse response ) throws IOException, URISyntaxException {
+ String sourcePathInfo = request.getPathInfo();
+ String sourcePattern = getConfig().getInitParameter( "pattern" );
+ String targetPattern = getConfig().getInitParameter( "target" );
+
+ //TODO: Some of the compilation should be done at servlet init for performance reasons.
+ Template sourceTemplate = Parser.parseTemplate( sourcePattern );
+ Template targetTemplate = Parser.parseTemplate( targetPattern );
+
+ Resolver resolver = new DispatchParamResolver( getConfig(), request );
+ URI sourceUri = new URI( sourcePathInfo );
+ URI targetUri = Rewriter.rewrite( sourceUri, sourceTemplate, targetTemplate, resolver, null );
+
+// //TODO: This should be more at filter init.
+// Pattern sourceRegex = UrlRewriter.compileUrlRegex( sourcePattern );
+// Matcher matcher = sourceRegex.matcher( sourcePathInfo );
+// String targetUrl = MessageFormat.format( targetPattern, Regex.toGroupArray( matcher ) );
+// System.out.println( "Source URI: " + expect.getRequestURI() );
+// System.out.println( "Source URL: " + expect.getRequestURL() );
+// System.out.println( "Source Query: " + expect.getQueryString() );
+// System.out.println( "Source pathInfo: " + sourcePathInfo );
+// System.out.println( "Source pattern: " + sourcePattern );
+// System.out.println( "Target pattern: " + targetPattern );
+// System.out.println( "Resolved target: " + targetUrl );
+
+ StringBuilder paramStr = new StringBuilder();
+ Enumeration paramNames = request.getParameterNames();
+ if( paramNames.hasMoreElements() ) {
+ paramStr.append( "?" );
+ }
+ while( paramNames.hasMoreElements() ) {
+ String paramName = (String)paramNames.nextElement();
+ String paramValue = request.getParameter( paramName );
+ paramStr.append( paramName );
+ paramStr.append( "=" );
+ paramStr.append( URLEncoder.encode( paramValue, "UTF-8" ) );
+ if( paramNames.hasMoreElements() ) {
+ paramStr.append( "&" );
+ }
+ }
+ String urlStr = targetUri.toString() + paramStr.toString();
+ try {
+ URL clientUrl = new URL( urlStr );
+ //System.out.println( "Resolved query: " + clientUrl );
+ AuthenticatedURL.Token token = new AuthenticatedURL.Token();
+ KerberosAuthenticator authenticator = new KerberosAuthenticator();
+ auditor.audit( Action.DISPATCH, urlStr, ResourceType.URI, ActionOutcome.UNAVAILABLE );
+ HttpURLConnection conn = new AuthenticatedURL( authenticator ).openConnection( clientUrl, token );
+ //System.out.println( "STATUS=" + conn.getResponseCode() );
+ InputStream input = conn.getInputStream();
+ if( input != null ) {
+ OutputStream output = response.getOutputStream();
+ try {
+ IOUtils.copy( input, output );
+ } finally {
+ //KNOX-685: output.flush();
+ input.close();
+ }
+ }
+ auditor.audit( Action.DISPATCH, urlStr, ResourceType.URI, ActionOutcome.SUCCESS );
+ } catch( AuthenticationException e ) {
+ response.sendError( HttpServletResponse.SC_UNAUTHORIZED );
+ LOG.failedToEstablishConnectionToUrl( urlStr, e );
+ auditor.audit( Action.DISPATCH, urlStr, ResourceType.URI, ActionOutcome.FAILURE, RES.responseStatus( HttpServletResponse.SC_UNAUTHORIZED ) );
+ } catch( FileNotFoundException e ) {
+ response.sendError( HttpServletResponse.SC_NOT_FOUND );
+ LOG.failedToEstablishConnectionToUrl( urlStr, e );
+ auditor.audit( Action.DISPATCH, urlStr, ResourceType.URI, ActionOutcome.FAILURE, RES.responseStatus( HttpServletResponse.SC_NOT_FOUND ) );
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-server/src/main/java/org/apache/knox/gateway/topology/validation/TopologyValidator.java
----------------------------------------------------------------------
diff --cc gateway-server/src/main/java/org/apache/knox/gateway/topology/validation/TopologyValidator.java
index 2c51535,0000000..1d3b00c
mode 100644,000000..100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/topology/validation/TopologyValidator.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/topology/validation/TopologyValidator.java
@@@ -1,122 -1,0 +1,122 @@@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.knox.gateway.topology.validation;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import javax.xml.XMLConstants;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.apache.knox.gateway.topology.Topology;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+public class TopologyValidator {
+
+ private Collection<String> errors = null;
+ private final String filePath;
+
+ public TopologyValidator(Topology t){
+ filePath = t.getUri().getPath();
+ }
+
+ public TopologyValidator(String path){
+ this.filePath = path;
+ }
+
+ public TopologyValidator(URL file){
+ filePath = file.getPath();
+ }
+
+ public boolean validateTopology() {
+ errors = new LinkedList<String>();
+ try {
+ SchemaFactory fact = SchemaFactory
+ .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ URL schemaUrl = getClass().getResource( "/conf/topology-v1.xsd" );
+ Schema s = fact.newSchema( schemaUrl );
+ Validator validator = s.newValidator();
+ final List<SAXParseException> exceptions = new LinkedList<>();
+ validator.setErrorHandler(new ErrorHandler() {
+ public void warning(SAXParseException exception) throws SAXException {
+ exceptions.add(exception);
+ }
+
+ public void fatalError(SAXParseException exception) throws SAXException {
+ exceptions.add(exception);
+ }
+
+ public void error(SAXParseException exception) throws SAXException {
+ exceptions.add(exception);
+ }
+ });
+
+ File xml = new File(filePath);
+ validator.validate(new StreamSource(xml));
- if(exceptions.size() > 0) {
++ if(!exceptions.isEmpty()) {
+ for (SAXParseException e : exceptions) {
+ errors.add("Line: " + e.getLineNumber() + " -- " + e.getMessage());
+ }
+ return false;
+ } else {
+ return true;
+ }
+
+ } catch (IOException e) {
+ errors.add("Error reading topology file");
+ errors.add(e.getMessage());
+ return false;
+ } catch (SAXException e) {
+ errors.add("There was a fatal error in parsing the xml file.");
+ errors.add(e.getMessage());
+ return false;
+ } catch (NullPointerException n) {
+ errors.add("Error retrieving schema from ClassLoader");
+ return false;
+ }
+ }
+
+ public Collection<String> getTopologyErrors(){
+
+ if(errors != null){
+ return errors;
+ }else{
+ validateTopology();
+ return errors;
+ }
+ }
+
+ public String getErrorString(){
+ StringBuilder out = new StringBuilder();
+ out.append("");
+ for(String s : getTopologyErrors()){
+ out.append(s + "\n");
+ }
+ return out.toString();
+ }
+
+}