/** * Copyright (c) 2015, Lucee Assosication Switzerland. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ package lucee.runtime.osgi; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.StringTokenizer; import java.util.jar.Attributes; import java.util.jar.Attributes.Name; import java.util.jar.Manifest; import lucee.aprint; import lucee.commons.lang.ExceptionUtil; import lucee.commons.lang.StringUtil; import lucee.runtime.type.util.ListUtil; public class ManifestUtil { private static final int DEFAULT_MAX_LINE_SIZE=100; private static final Set<String> DEFAULT_MAIN_FILTER=new HashSet<String>(); static { DEFAULT_MAIN_FILTER.add("Manifest-Version"); } private static final Set<String> DEFAULT_INDIVIDUAL_FILTER=new HashSet<String>(); static { DEFAULT_INDIVIDUAL_FILTER.add("Name"); } public static String toString(Manifest manifest, int maxLineSize, Set<String> mainSectionIgnore,Set<String> individualSectionIgnore) { if(maxLineSize<0) maxLineSize=DEFAULT_MAX_LINE_SIZE; StringBuilder msb=new StringBuilder(); Attributes main = manifest.getMainAttributes(); // prepare ignores if(mainSectionIgnore==null)mainSectionIgnore=DEFAULT_MAIN_FILTER; else mainSectionIgnore.addAll(DEFAULT_MAIN_FILTER); if(individualSectionIgnore==null)individualSectionIgnore=DEFAULT_INDIVIDUAL_FILTER; else individualSectionIgnore.addAll(DEFAULT_INDIVIDUAL_FILTER); // Manifest-Version comes first add(msb,"Manifest-Version",main.getValue("Manifest-Version"),"1.0"); // all other main attributes printSection(msb,main,maxLineSize,mainSectionIgnore); // individual entries Map<String, Attributes> entries = manifest.getEntries(); if(entries!=null && entries.size()>0) { Iterator<Entry<String, Attributes>> it = entries.entrySet().iterator(); Entry<String, Attributes> e; StringBuilder sb; while(it.hasNext()){ e = it.next(); sb=new StringBuilder(); printSection(sb,e.getValue(),maxLineSize,individualSectionIgnore); if(sb.length()>0) { msb.append('\n'); // new section need a empty line add(msb,"Name", e.getKey(), null); msb.append(sb); } } } return msb.toString(); } private static void printSection(StringBuilder sb, Attributes attrs, int maxLineSize, Set<String> ignore) { Iterator<Entry<Object, Object>> it = attrs.entrySet().iterator(); Entry<Object, Object> e; String name; String value; while(it.hasNext()){ e = it.next(); name=((Name)e.getKey()).toString(); value=(String)e.getValue(); if(StringUtil.isEmpty(value)) continue; //aprint.e("Export-Package:"+name+":"+("Export-Package".equals(name))); if("Import-Package".equals(name) || "Export-Package".equals(name) || "Require-Bundle".equals(name)) { value=splitByComma(value); } else if(value.length()>maxLineSize) value=split(value,maxLineSize); if(ignore!=null && ignore.contains(name)) continue; add(sb,name,value,null); } } private static String splitByComma(String value) { StringTokenizer st=new StringTokenizer(value.trim(),","); StringBuilder sb=new StringBuilder(); while(st.hasMoreTokens()){ if(sb.length()>0) sb.append(",\n "); sb.append(st.nextToken().trim()); } return sb.toString(); } private static String split(String value, int max) { StringTokenizer st=new StringTokenizer(value,"\n"); StringBuilder sb=new StringBuilder(); while(st.hasMoreTokens()){ _split(sb,st.nextToken(), max); } return sb.toString(); } private static void _split(StringBuilder sb,String value, int max) { int index=0; while(index+max <= value.length()){ if(sb.length()>0)sb.append("\n "); sb.append(value.substring(index,index+max)); index=index+max; } if(index<value.length()) { if(sb.length()>0)sb.append("\n "); sb.append(value.substring(index,value.length())); } } private static void add(StringBuilder sb, String name, String value, String defaultValue) { if(value==null) { if(defaultValue==null) return; value=defaultValue; } sb.append(name).append(": ").append(value).append('\n'); } public static void removeFromList(Attributes attrs,String key, String valueToRemove) { String val = attrs.getValue(key); if(StringUtil.isEmpty(val)) return; StringBuilder sb=new StringBuilder(); boolean removed=false; boolean wildcard=false; if(valueToRemove.endsWith(".*")) { wildcard=true; valueToRemove=valueToRemove.substring(0,valueToRemove.length()-1); } try { Iterator<String> it = toList(val).iterator();//ListUtil.toStringArray(ListUtil.listToArrayTrim(val, ',')); String str; while(it.hasNext()){ str=it.next(); str=str.trim(); //print.e("=="+str); if(wildcard?str.startsWith(valueToRemove):(str.equals(valueToRemove) || ListUtil.first(str, ";").trim().equals(valueToRemove))) { removed=true; continue; } if(sb.length()>0)sb.append(",\n "); sb.append(str); } } catch (Throwable e) { ExceptionUtil.rethrowIfNecessary(e); } if(removed) { if(sb.length()>0) attrs.putValue(key, sb.toString()); else attrs.remove(key); } } public static void removeOptional(Attributes attrs,String key) { String val = attrs.getValue(key); if(StringUtil.isEmpty(val)) return; StringBuilder sb=new StringBuilder(); boolean removed=false; try { Iterator<String> it = toList(val).iterator();//ListUtil.toStringArray(ListUtil.listToArrayTrim(val, ',')); String str; while(it.hasNext()){ str=it.next(); str=str.trim(); //print.e("=="+str); if(str.indexOf("resolution:=optional")!=-1) { removed=true; aprint.e("+"+str); continue; } if(sb.length()>0)sb.append(",\n "); sb.append(str); } } catch (Throwable e) { ExceptionUtil.rethrowIfNecessary(e); } if(removed) attrs.putValue(key, sb.toString()); } private static List<String> toList(String val) { List<String> list=new ArrayList<String>(); int len=val.length(); int inside=0; char c; int begin=0; for(int i=0;i<len;i++){ c=val.charAt(i); if(c=='"') { if(inside=='"')inside=0; else if(inside==0)inside='"'; } else if(c=='\'') { if(inside=='\'')inside=0; else if(inside==0)inside='\''; } else if(c==',' && inside==0) { if(begin<i)list.add(val.substring(begin,i)); begin=i+1; } } if(begin<len) list.add(val.substring(begin)); return list; } }