/* * 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.felix.configurator.impl; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.osgi.framework.Bundle; import org.osgi.util.converter.Converter; import org.osgi.util.converter.StandardConverter; import org.osgi.util.converter.TypeReference; public class TypeConverter { public static Converter getConverter() { return new StandardConverter(); } private final List<File> allFiles = new ArrayList<File>(); private final List<File> files = new ArrayList<File>(); private final Bundle bundle; /** * Create a new instance * @param bundle The bundle, might be {@code null}. */ public TypeConverter(final Bundle bundle) { this.bundle = bundle; } /** * Convert a value to the given type * @param value The value * @param typeInfo Optional type info, might be {@code null} * @return The converted value or {@code null} if the conversion failed. * @throws IOException If an error happens */ public Object convert( final String pid, final Object value, final String typeInfo) throws IOException { if ( typeInfo == null ) { if ( value instanceof String || value instanceof Boolean ) { return value; } else if ( value instanceof Long || value instanceof Double ) { return value; } else if ( value instanceof Integer ) { return ((Integer)value).longValue(); } else if ( value instanceof Short ) { return ((Short)value).longValue(); } else if ( value instanceof Byte ) { return ((Byte)value).longValue(); } else if ( value instanceof Float ) { return ((Float)value).doubleValue(); } if ( value instanceof List ) { @SuppressWarnings("unchecked") final List<Object> list = (List<Object>)value; if ( list.isEmpty() ) { return new String[0]; } final Object firstObject = list.get(0); if ( firstObject instanceof String ) { return getConverter().convert(list).defaultValue(null).to(String[].class); } else if ( firstObject instanceof Boolean ) { return getConverter().convert(list).defaultValue(null).to(Boolean[].class); } else if ( firstObject instanceof Long || firstObject instanceof Integer ) { return getConverter().convert(list).defaultValue(null).to(Long[].class); } else if ( firstObject instanceof Double || firstObject instanceof Float ) { return getConverter().convert(list).defaultValue(null).to(Double[].class); } } return null; } // binary if ( "binary".equals(typeInfo) ) { if ( bundle == null ) { throw new IOException("Binary files only allowed within a bundle"); } final String path = getConverter().convert(value).defaultValue(null).to(String.class); if ( path == null ) { throw new IOException("Invalid path for binary property: " + value); } final File filePath = Util.extractFile(bundle, pid, path); if ( filePath == null ) { throw new IOException("Invalid path for binary property: " + value); } files.add(filePath); allFiles.add(filePath); return filePath.getAbsolutePath(); } else if ( "binary[]".equals(typeInfo) ) { if ( bundle == null ) { throw new IOException("Binary files only allowed within a bundle"); } final String[] paths = getConverter().convert(value).defaultValue(null).to(String[].class); if ( paths == null ) { throw new IOException("Invalid paths for binary[] property: " + value); } final String[] filePaths = new String[paths.length]; int i = 0; while ( i < paths.length ) { final File filePath = Util.extractFile(bundle, pid, paths[i]); if ( filePath == null ) { throw new IOException("Invalid path for binary property: " + value); } files.add(filePath); allFiles.add(filePath); filePaths[i] = filePath.getAbsolutePath(); i++; } return filePaths; } // scalar types and primitive types if ( "String".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(String.class); } else if ( "Integer".equals(typeInfo) || "int".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Integer.class); } else if ( "Long".equals(typeInfo) || "long".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Long.class); } else if ( "Float".equals(typeInfo) || "float".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Float.class); } else if ( "Double".equals(typeInfo) || "double".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Double.class); } else if ( "Byte".equals(typeInfo) || "byte".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Byte.class); } else if ( "Short".equals(typeInfo) || "short".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Short.class); } else if ( "Character".equals(typeInfo) || "char".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Character.class); } else if ( "Boolean".equals(typeInfo) || "boolean".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Boolean.class); } // array of scalar types and primitive types if ( "String[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(String[].class); } else if ( "Integer[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Integer[].class); } else if ( "int[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(int[].class); } else if ( "Long[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Long[].class); } else if ( "long[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(long[].class); } else if ( "Float[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Float[].class); } else if ( "float[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(float[].class); } else if ( "Double[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Double[].class); } else if ( "double[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(double[].class); } else if ( "Byte[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Byte[].class); } else if ( "byte[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(byte[].class); } else if ( "Short[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Short[].class); } else if ( "short[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(short[].class); } else if ( "Character[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Character[].class); } else if ( "char[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(char[].class); } else if ( "Boolean[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(Boolean[].class); } else if ( "boolean[]".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(boolean[].class); } // Collections of scalar types if ( "Collection<String>".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(new TypeReference<List<String>>() {}); } else if ( "Collection<Integer>".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(new TypeReference<List<Integer>>() {}); } else if ( "Collection<Long>".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(new TypeReference<List<Long>>() {}); } else if ( "Collection<Float>".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(new TypeReference<List<Float>>() {}); } else if ( "Collection<Double>".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(new TypeReference<List<Double>>() {}); } else if ( "Collection<Byte>".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(new TypeReference<List<Byte>>() {}); } else if ( "Collection<Short>".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(new TypeReference<List<Short>>() {}); } else if ( "Collection<Character>".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(new TypeReference<List<Character>>() {}); } else if ( "Collection<Boolean>".equals(typeInfo) ) { return getConverter().convert(value).defaultValue(null).to(new TypeReference<List<Boolean>>() {}); } // unknown type - ignore configuration throw new IOException("Invalid type information: " + typeInfo); } public void cleanupFiles() { for(final File f : allFiles) { f.delete(); } } public List<File> flushFiles() { if ( this.files.isEmpty() ) { return null; } else { final List<File> result = new ArrayList<>(this.files); this.files.clear(); return result; } } }