001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 package org.apache.xbean.osgi.bundle.util; 020 021 import java.util.ArrayList; 022 import java.util.HashMap; 023 import java.util.List; 024 import java.util.Map; 025 026 /** 027 * Utility class to parse standard OSGi headers. 028 * 029 * @version $Rev: 937957 $, $Date: 2010-04-26 10:00:08 +0200 (Mon, 26 Apr 2010) $ 030 */ 031 public class HeaderParser { 032 033 /** 034 * Parse a given OSGi header into a list of header elements. 035 * 036 * @param header the OSGi header to parse 037 * @return the list of header elements extracted from this header 038 */ 039 public static List<HeaderElement> parseHeader(String header) { 040 List<HeaderElement> elements = new ArrayList<HeaderElement>(); 041 if (header == null || header.trim().length() == 0) { 042 return elements; 043 } 044 List<String> clauses = parseDelimitedString(header, ",", false); 045 for (String clause : clauses) { 046 String[] tokens = clause.split(";"); 047 if (tokens.length < 1) { 048 throw new IllegalArgumentException("Invalid header clause: " + clause); 049 } 050 HeaderElement elem = new HeaderElement(tokens[0].trim()); 051 elements.add(elem); 052 for (int i = 1; i < tokens.length; i++) { 053 int pos = tokens[i].indexOf('='); 054 if (pos != -1) { 055 if (pos > 0 && tokens[i].charAt(pos - 1) == ':') { 056 String name = tokens[i].substring(0, pos - 1).trim(); 057 String value = tokens[i].substring(pos + 1).trim(); 058 elem.addDirective(name, value); 059 } else { 060 String name = tokens[i].substring(0, pos).trim(); 061 String value = tokens[i].substring(pos + 1).trim(); 062 elem.addAttribute(name, value); 063 } 064 } else { 065 elem = new HeaderElement(tokens[i].trim()); 066 elements.add(elem); 067 } 068 } 069 } 070 return elements; 071 } 072 073 private static List<String> parseDelimitedString(String value, String delim, boolean includeQuotes) { 074 if (value == null) { 075 value = ""; 076 } 077 078 List<String> list = new ArrayList<String>(); 079 080 int CHAR = 1; 081 int DELIMITER = 2; 082 int STARTQUOTE = 4; 083 int ENDQUOTE = 8; 084 085 StringBuffer sb = new StringBuffer(); 086 087 int expecting = (CHAR | DELIMITER | STARTQUOTE); 088 089 for (int i = 0; i < value.length(); i++) { 090 char c = value.charAt(i); 091 092 boolean isDelimiter = (delim.indexOf(c) >= 0); 093 boolean isQuote = (c == '"'); 094 095 if (isDelimiter && ((expecting & DELIMITER) > 0)) { 096 list.add(sb.toString().trim()); 097 sb.delete(0, sb.length()); 098 expecting = (CHAR | DELIMITER | STARTQUOTE); 099 } else if (isQuote && ((expecting & STARTQUOTE) > 0)) { 100 if (includeQuotes) { 101 sb.append(c); 102 } 103 expecting = CHAR | ENDQUOTE; 104 } else if (isQuote && ((expecting & ENDQUOTE) > 0)) { 105 if (includeQuotes) { 106 sb.append(c); 107 } 108 expecting = (CHAR | STARTQUOTE | DELIMITER); 109 } else if ((expecting & CHAR) > 0) { 110 sb.append(c); 111 } else { 112 throw new IllegalArgumentException("Invalid delimited string: " + value); 113 } 114 } 115 116 if (sb.length() > 0) { 117 list.add(sb.toString().trim()); 118 } 119 120 return list; 121 } 122 123 public static class HeaderElement { 124 125 private String path; 126 private Map<String, String> attributes; 127 private Map<String, String> directives; 128 129 public HeaderElement(String path) { 130 this.path = path; 131 this.attributes = new HashMap<String, String>(); 132 this.directives = new HashMap<String, String>(); 133 } 134 135 public String getName() { 136 return this.path; 137 } 138 139 public Map<String, String> getAttributes() { 140 return attributes; 141 } 142 143 public String getAttribute(String name) { 144 return attributes.get(name); 145 } 146 147 public void addAttribute(String name, String value) { 148 attributes.put(name, value); 149 } 150 151 public Map<String, String> getDirectives() { 152 return directives; 153 } 154 155 public String getDirective(String name) { 156 return directives.get(name); 157 } 158 159 public void addDirective(String name, String value) { 160 directives.put(name, value); 161 } 162 163 } 164 }