/******************************************************************************* * Copyright (c) 2008, 2011 VMware Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VMware Inc. - initial contribution *******************************************************************************/ package org.eclipse.virgo.management.console.internal; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.Map; import java.util.Scanner; /** * @author cgfrost * */ public class Parser { private static final String START_DECLARATION = "<!--@"; private static final String END_DECLARATION = "@-->"; private static final char IMPORT = '&'; // Replace the declaration with another file that will also be parsed, value can be a lookup. private static final char SET = '>'; //Place the given value in to the page context, 'String:String'. private static final char LOOKUP = '<'; // Replace the declaration with a lookup from the page context. private static final char EVALUATE = '?'; // Replace the declaration with a the result of an evaluation. private final Map<String, String> pageContext; private final PrintWriter out; private final ContentURLFetcher urlFetcher; /** * * @param out * @param modelData */ public Parser(PrintWriter out, ContentURLFetcher urlFetcher, Map<String, String> modelData) { this.out = out; this.urlFetcher = urlFetcher; this.pageContext = modelData; } /** * * @param in */ public final void parse(InputStream in) throws IOException { try (Scanner scanner = new Scanner(in)) { String parsedLine; while (scanner.hasNextLine()) { parsedLine = parseLine(scanner.nextLine()); if (parsedLine != null && !parsedLine.trim().isEmpty()) { out.append(parsedLine); out.append('\n'); } } } } private String parseLine(String line) throws IOException { int startOffset = line.indexOf(START_DECLARATION); if(startOffset > -1){ int endOffset = line.indexOf(END_DECLARATION); if(endOffset > startOffset){ String arg = line.substring(startOffset + START_DECLARATION.length() + 1, endOffset); String newValue = ""; switch (line.charAt(startOffset + START_DECLARATION.length())) { case IMPORT: newValue = doImport(arg); break; case SET: newValue = doSet(arg); break; case LOOKUP: newValue = doLookup(arg); break; case EVALUATE: newValue = doEvaluate(arg); break; default: //Unknown command, do nothing break; } line = String.format("%s%s%s", line.substring(0, startOffset), newValue, line.substring(endOffset + END_DECLARATION.length())); line = parseLine(line);// There might be further declarations in the line. } } return line; } private String doImport(String arg) throws IOException { arg = resolveField(arg); if(arg.charAt(0) != '/'){ arg = '/' + arg; } URL content = this.urlFetcher.getRequestedContentURL(arg); URLConnection resourceConn = content.openConnection(); InputStream in = resourceConn.getInputStream(); try { this.parse(in); } finally { in.close(); } return ""; } private String doSet(String arg) { int splitOffSet = arg.indexOf(':'); if(splitOffSet >= 0){ this.pageContext.put(arg.substring(0, splitOffSet), arg.substring(splitOffSet + 1)); } return ""; } private String doLookup(String arg){ String newValue = this.pageContext.get(arg); if(newValue == null){ return ""; } return newValue; } private String doEvaluate(String arg) { int equalsOffset = arg.indexOf('='); int thenOffset = arg.indexOf(':'); int elseOffset = arg.indexOf(':', thenOffset + 1); boolean result; if(equalsOffset >= 0 && equalsOffset < thenOffset){ String query = resolveField(arg.substring(0, equalsOffset)); String comparator = resolveField(arg.substring(equalsOffset + 1, thenOffset)); result = query.equals(comparator); } else { String query = resolveField(arg.substring(0, thenOffset)); result = Boolean.valueOf(query); } if(result){ return resolveField(arg.substring(thenOffset + 1, elseOffset)); } else { return ((elseOffset + 1) == arg.length()) ? "" : resolveField(arg.substring(elseOffset + 1)); } } private String resolveField(String field){ if(field.charAt(0) == LOOKUP){ field = this.doLookup(field.substring(1)); } else if (field.charAt(0) == SET){ field = this.doSet(field).substring(1); } return field; } }