<<上篇 | 首页 | 下篇>>

解析获取Xml Encoding字符集Charset

    /*
     * Given a URI string, open it, read its contents into a String
     * and return the String
     *
     *@param uri the URI to open
     *@return the content at the URI or null if any error occurs
     */
    private String getRDFfromURI (String uri) throws getRDFException
    {
        /* add something like this code here, to allow reading from a file:
           (if we really want to allow this!)
           File ff = new File(uri);
           in = new FileInputStream(ff);
        */
        URL url = null;
        try {
            url = new URL(uri);
        } catch (MalformedURLException e) {
            throw new getRDFException("Malformed URI.");
        }
 
        URLConnection con = null;
        try {
            con = url.openConnection();
            con.setRequestProperty("Accept", "application/rdf+xml");
            con.connect();
        } catch (Exception e) {
            throw new getRDFException("Unable to open connection.");
        }
        String contentT = con.getContentType();
        String HTTPcharset = null;
        if (contentT != null) {
            ContentType contentType = null;
            try {
                contentType = new ContentType(con.getContentType());
            } catch (javax.mail.internet.ParseException e) {
                throw new getRDFException("Unparsable content type.");
            }
            HTTPcharset = contentType.getParameter("charset");
        }
 
        // need buffer for lookahead for encoding detection
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(con.getInputStream());
        } catch (IOException e) {
            throw new getRDFException("Cannot open stream.");
        }
        bis.mark(200); // mark start so that we can get back to it
        String s = "";
 
        try { // read start of file as bytes
            int c;
            int numRead = 0;
            while ((c = bis.read()) != -1) {
                s += (char)c;
                if (numRead++ >= 195) break;
            }
        } catch (IOException e) {
            throw new getRDFException("IOException while starting reading.");
        }
 
        if (s.equals(""))
            // Nothing was returned
            throw new getRDFException("Empty document, ignored.");
 
        // A server could return content but not the RDF/XML that
        // we need.  Check the beginning of s and if it looks like
        // a generic HTML message, return an error.
        if (s.startsWith("<!DOCTYPE"))
            throw new getRDFException("Document looks like HTML, ignored.");
 
        String APPFcharset = null; // 'charset' according to XML APP. F
        int ignoreBytes = 0;
        if (s.startsWith("\u00FE\u00FF")) {
            APPFcharset = "UTF-16BE";
            ignoreBytes = 2;
        }
        else if (s.startsWith("\u00FF\u00FE")) {
            APPFcharset = "UTF-16LE";
            ignoreBytes = 2;
        }
        else if (s.startsWith("\u00EF\u00BB\u00BF")) {
            APPFcharset = "UTF-8";
            ignoreBytes = 3;
        }
        else if (s.startsWith("\u0000<\u0000?")) {
            APPFcharset = "UTF-16BE";
        }
        else if (s.startsWith("<\u0000?\u0000")) {
            APPFcharset = "UTF-16LE";
        }
        else if (s.startsWith("<?xml")) {
            APPFcharset = "iso-8859-1"; //to not loose any bytes
        }
        else if (s.startsWith("\u004C\u006F\u00A7\u0094")) {
            APPFcharset = "CP037"; // EBCDIC
        }
        else {
            APPFcharset = "iso-8859-1"; //to not loose any bytes
        }
 
        // convert start of xml input according to APPFcharset
        String xmlstart = null;
        try {
//          System.err.println("---------------------------");
//          System.err.println("ignoreBytes="+ignoreBytes);
//          System.err.println("s="+s);
//          System.err.println("APPFcharset="+APPFcharset);
//          if (APPFcharset!=null){xmlstart = new String(s.substring(ignoreBytes).getBytes("iso-8859-1"), APPFcharset);}
//          else {xmlstart=new String(s.substring(ignoreBytes).getBytes("iso-8859-1"));APPFcharset = "UTF-8";}
            xmlstart = new String(s.substring(ignoreBytes).getBytes("iso-8859-1"), APPFcharset);
        } catch (UnsupportedEncodingException e) {
            throw new getRDFException("Unsupported encoding '"+APPFcharset+"'.");
        }
        RE r;
        try {
            r = new RE("<\\?xml[ \\t\\n\\r]+version[ \\t\\n\\r]?=[ \\t\\n\\r]?(['\"])([a-zA-Z0-9_:]|\\.|-)+\\1[ \\t\\n\\r]+encoding[ \\t\\n\\r]?=[ \\t\\n\\r]?(['\"])([A-Za-z]([A-Za-z0-9._]|-)*)\\3");
        } catch (RESyntaxException res) {
            throw new getRDFException("Wrong regular expression syntax.");
        }
        // r.setMatchFlags(MATCH_NORMAL | MATCH_SINGLELINE);
        String XMLcharset = null;
        if (r.match(xmlstart) && r.getParenStart(0)==0)
            XMLcharset = r.getParen(4);
        if (HTTPcharset != null)
            HTTPcharset = HTTPcharset.toUpperCase();
        if (XMLcharset != null)
            XMLcharset = XMLcharset.toUpperCase();
 
        String finalCharset = null;
        if (HTTPcharset != null) {
            if (XMLcharset != null && !HTTPcharset.equals(XMLcharset))
                throw new getRDFException("Charset conflict: Content-Type: "
                    + contentT+ ". XML encoding: " + XMLcharset + ".");
            finalCharset = HTTPcharset;
        }
        else if (XMLcharset != null)
            finalCharset = XMLcharset;
        if ((finalCharset != null && finalCharset.equals("UTF-16")) ||
                (finalCharset == null && APPFcharset.startsWith("UTF-16")))
            if (ignoreBytes == 2)
                finalCharset = APPFcharset; // use correct endianness
            else
                throw new getRDFException("Illegal XML: UTF-16 without BOM.");
        if (finalCharset == null)
            finalCharset = "UTF-8";
 
        try {
            bis.reset();                 // move back to start of stream
            bis.skip(ignoreBytes);       // skip BOM
        } catch (IOException e) {
            throw new getRDFException("IOException while resetting stream.");
        }
 
        InputStreamReader isr = null;
        try {
            isr = new InputStreamReader(bis, finalCharset);
        } catch (UnsupportedEncodingException e) {
            throw new getRDFException("Unsupported encoding '"+finalCharset+"'.");
        }
        StringBuffer sb=new StringBuffer("");
        int bytenum=0;
        try {// read whole file as characters
            int c;
            while ((c = isr.read()) != -1) {
                sb.append((char)c);
                bytenum++;
            }
        }
        catch (IOException e){
            throw new getRDFException("Undecodable data when reading URI at byte "+bytenum+" using encoding '"+finalCharset+"'."+" Please check encoding and encoding declaration of your document.");
        }
        // todo: fix encoding parameter in xml pseudo-PI
        return sb.toString();
    }

阅读全文……

标签 :

同时入选IMDB和豆瓣电影100强的经典电影

导演 : 弗兰克·德拉邦特 Frank Darabont 
主演 : 蒂姆·罗宾斯 Tim Robbins/摩根·弗里曼 Morgan Freeman/鲍勃·冈顿 Bob Gunton/威廉姆·赛德勒 William Sadler/克兰西·布朗 Clancy Brown

 

 

2009-05-19 添加2. 教父 The Godfather

导演 : 弗朗西斯·福特·科波拉 Francis Ford Coppola 
主演 : 马龙·白兰度 Marlon Brando/阿尔·帕西诺 Al Pacino/詹姆斯·凯恩 James Caan/罗伯特·杜瓦尔 Robert Duvall/黛安·基顿 Diane Keaton

 

 

2009-05-19 添加3. 教父2 The Godfather: Part Ⅱ

导演 : Francis Ford Coppola 
主演 : Al Pacino/Robert Duvall/Robert De Niro/Diane Keaton/John Cazale

 

 

2009-05-19 添加4. 低俗小说 Pulp Fiction

导演 : 昆汀·塔伦蒂诺 Quentin Tarantino 
主演 : 乌玛·瑟曼 Uma Thurman/塞缪尔·杰克逊 Samuel L. Jackson/约翰·特拉沃塔 John Travolta/蒂姆·罗斯 Tim Roth/布鲁斯·威利斯 Bruce Willis

 

 

导演 : Steven Spielberg 
主演 : Liam Neeson/Ben Kingsley/Ralph Fiennes/Caroline Goodall/Jonathan Sagall

 

 

导演 : 米洛斯·福尔曼 Miloš Forman 
主演 : 杰克·尼科尔森 Jack Nicholson/丹尼·德维托 Danny DeVito/克里斯托弗·洛伊德 Christopher Lloyd/路易丝·弗莱彻 Louise Fletcher/Ted Markland/布拉德·道里夫 Brad Dourif

 

 

2009-05-19 添加7. 七武士 七人の侍

导演 : 黑泽明 
主演 : 三船敏郎 Toshirô Mifune/志村乔 Takashi Shimura/稻叶义男 Yoshio Inaba/宫口精二 Seiji Miyaguchi/千秋实 Minoru Chiaki/加东大介 Daisuke Katô/木村功 Isao Kimura

 

 

导演 : 彼得·杰克逊 Peter Jackson 
主演 : 维果·莫腾森 Viggo Mortensen/伊利亚·伍德 Elijah Wood/西恩·奥斯汀 Sean Astin/丽芙·泰勒 Liv Tyler/伊恩·麦克莱恩 Ian McKellen/奥兰多·布鲁姆 Orlando Bloom/凯特·布兰切特 Cate Blanchett/米兰达·奥图 Miranda Otto/安迪·瑟金斯 Andy Serkis/雨果·维文 Hugo Weaving/多米尼克·莫纳汉 Dominic Monaghan/比利·博伊德 Billy Boyd/马尔顿·索克斯 Marton Csokas/卡尔·厄本 Karl Urban/克里斯托弗·李 Christopher Lee/约翰·瑞斯-戴维斯 John Rhys-Davies

 

 

2009-05-19 添加9. 上帝之城 Cidade de Deus

导演 : Fernando Meirelles/Kátia Lund 
主演 : Alexandre Rodrigues/Matheus Nachtergaele/Douglas Silva/Leandro Firmino/Jonathan Haagensen

 

 

导演 : 彼得·杰克逊 Peter Jackson 
主演 : 伊利亚·伍德 Elijah Wood/西恩·奥斯汀 Sean Astin/伊恩·麦克莱恩 Ian McKellen/维果·莫腾森 Viggo Mortensen/奥兰多·布鲁姆 Orlando Bloom/凯特·布兰切特 Cate Blanchett/肖恩·宾 Sean Bean/克里斯托弗·李 Christopher Lee/雨果·维文 Hugo Weaving/丽芙·泰勒 Liv Tyler/安迪·瑟金斯 Andy Serkis/伊安·霍姆 Ian Holm/多米尼克·莫纳汉 Dominic Monaghan/萨拉·贝克 Sala Baker/约翰·瑞斯-戴维斯 John Rhys-Davies

 

 

2009-05-19 添加11. 搏击俱乐部 Fight Club

导演 : 大卫·芬奇 David Fincher 
主演 : 爱德华·诺顿 Edward Norton/布拉德·皮特 Brad Pitt/海伦娜·邦汉·卡特 Helena Bonham Carter/杰瑞德·莱托 Jared Leto/艾恩·贝利 Eion Bailey

 

 

2009-05-19 添加12. 这个杀手不太冷 Léon

导演 : 吕克·贝松 Luc Besson 
主演 : 让·雷诺 Jean Reno/娜塔丽·波特曼 Natalie Portman/加里·奥德曼 Gary Oldman/丹尼·爱罗 Danny Aiello/麦温·勒·贝斯柯 Maïwenn Le Besco

 

 

2009-05-19 添加13. 美丽人生 La vita è bella

导演 : 罗伯托·贝尼尼 Roberto Benigni 
主演 : 罗伯托·贝尼尼 Roberto Benigni/尼可莱塔·布拉斯基 Nicoletta Braschi/乔治·坎塔里尼 Giorgio Cantarini/Giustino Durano/Sergio Bini Bustric/玛丽莎·佩雷德斯 Marisa Paredes/豪斯特·巴奇霍兹 Horst Buchholz/Lidia Alfonsi/Giuliana Lojodice

 

 

导演 : 朱塞佩·托纳多雷 Giuseppe Tornatore 
主演 : 萨瓦特利·卡西欧 Salvatore Cascio/Enzo Cannavale/马克·莱昂纳蒂 Marco Leonardi/菲利浦·诺瓦雷 Philippe Noiret/安东娜拉 塔莉 Antonella Attili/雅克·贝汉 Jacques Perrin

 

 

导演 : 宫崎骏 Hayao Miyazaki 
主演 : 柊瑠美 Rumi Hîragi/入野自由 Miyu Irino/夏木真理 Mari Natsuki/菅原文太 Bunta Sugawara/内藤刚志 Takashi Naitô/神木隆之介 Ryûnosuke Kamiki

 

 

2009-06-07 添加16. 钢琴家 The Pianist

导演 : Roman Polanski 
主演 : Adrien Brody/Thomas Kretschmann/Emilia Fox/Julia Rayner/Jessica Kate Meyer

 

 

导演 : 彼得·杰克逊 Peter Jackson 
主演 : 伊利亚·伍德 Elijah Wood/西恩·奥斯汀 Sean Astin/伊恩·麦克莱恩 Ian McKellen/维果·莫腾森 Viggo Mortensen/奥兰多·布鲁姆 Orlando Bloom/克里斯托弗·李 Christopher Lee/丽芙·泰勒 Liv Tyler/安迪·瑟金斯 Andy Serkis/雨果·维文 Hugo Weaving/卡尔·厄本 Karl Urban/凯特·布兰切特 Cate Blanchett/多米尼克·莫纳汉 Dominic Monaghan/大卫·文翰 David Wenham/比利·博伊德 Billy Boyd/布拉德·道里夫 Brad Dourif/伯纳德·希尔 Bernard Hill/约翰·瑞斯-戴维斯 John Rhys-Davies

 

 

导演 : Sergio Leone 
主演 : 罗伯特·德尼罗 Robert De Niro/詹姆斯·伍兹 James Woods/詹妮弗·康纳利 Jennifer Connelly/伊丽莎白·麦戈文 Elizabeth McGovern/乔·佩西 Joe Pesci/塔斯黛·韦尔德 Tuesday Weld/波特·杨 Burt Young/特里特·威廉斯 Treat Williams/丹尼·爱罗 Danny Aiello/Richard Bright

 

 

2009-06-07 添加19. 阿甘正传 Forrest Gump

导演 : Robert Zemeckis 
主演 : Tom Hanks/Robin Wright Penn/Gary Sinise/Mykelti Williamson/Sally Field/Michael Conner Humphreys/Haley Joel Osment

 

 

导演 : Jean-Pierre Jeunet 
主演 : 奥黛丽·塔图 Audrey Tautou/马修·卡索维茨 Mathieu Kassovitz/贾梅尔·杜布兹 Jamel Debbouze/Lorella Cravotta/多米尼克·皮诺 Dominique Pinon/Isabelle Nanty/友兰达·梦露 Yolande Moreau/Rufus/克莱尔·莫里耶 Claire Maurier/艾特·迪·彭吉云 Artus de Penguern/Maurice Bénichou/米切尔·罗宾 Michel Robin/Serge Merlin/Clotilde Mollet/Urbain Cancelier/克劳德·佩龙 Claude Perron

 

 

导演 : 达伦·阿伦诺夫斯基 Darren Aronofsky 
主演 : 艾伦·伯斯汀 Ellen Burstyn/杰瑞德·莱托 Jared Leto/詹妮弗·康纳利 Jennifer Connelly/马龙·韦恩斯 Marlon Wayans/Christopher McDonald

 

 

2010-02-21 添加22. 机器人总动员 WALL·E

导演 : 安德鲁·斯坦顿 Andrew Stanton 
主演 : 本·贝尔特 Ben Burtt/艾丽莎·奈特 Elissa Knight/杰夫·格尔林 Jeff Garlin/佛莱德·威拉特 Fred Willard

 

 

导演 : 弗洛里安·亨克尔·冯·多纳斯马 Florian Henckel von Donnersmarck 
主演 : 乌尔里希·穆埃 Ulrich Mühe/马蒂娜·戈黛特 Martina Gedeck/塞巴斯蒂安·考奇 Sebastian Koch/乌尔里奇·图克尔 Ulrich Tukur/托马斯·席尔梅 Thomas Thieme

 

 

2010-02-21 添加24. 飞屋环游记 Up

导演 : 彼特·道格特 Pete Docter 
主演 : 克里斯托弗·普卢默 Christopher Plummer/约翰·拉岑贝格 John Ratzenberger/爱德华·阿斯纳 Edward Asner/Paul Eiding/乔丹·长井 Jordan Nagai

 

 

2010-02-21 添加25. 雨中曲 Singin' in the Rain

导演 : Stanley Donen/Gene Kelly 
主演 : Gene Kelly/Donald O'Connor/Debbie Reynolds/Cyd Charisse/Jean Hagen

阅读全文……

标签 : ,

Dynamic DataSource Routing | SpringSource Team Blog

Anyways, here's the code for my Catalog:

package blog.datasource;
 
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
 
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
 
public class Catalog extends SimpleJdbcDaoSupport {
 
   public List<Item> getItems() {
      String query = "select name, price from item";
      return getSimpleJdbcTemplate().query(query, new ParameterizedRowMapper<Item>() {
            public Item mapRow(ResultSet rs, int row) throws SQLException {
               String name = rs.getString(1);
               double price = rs.getDouble(2);
               return new Item(name, price);
            }
      });
   }
}

 

As you can see, the Catalog simply returns a list of Item objects. The Item just contains name and price properties:

package blog.datasource;
 
public class Item {
 
   private String name;
   private double price;
 
   public Item(String name, double price) {
      this.name = name;
      this.price = price;
   }
 
   public String getName() {
      return name;
   }
 
   public double getPrice() {
      return price;
   }
 
   public String toString() {
      return name + " (" + price + ")";
   }
 
}

 

Now, in order to demonstrate multiple DataSources, I created an enum for different Customer types (representing "levels" of membership I guess), and I created three different databases – so that each type of customer would get a distinct item list (I did mention that this would be a contrived example didn't I?). The important thing is that each of the databases are equivalent in terms of the schema. That way the Catalog's query will work against any of them – just returning different results. In this case, it's just the "item" table with 2 columns: name and price. And… here is the enum:

public enum CustomerType {
   BRONZE,
   SILVER,
   GOLD
}

 

It's time to create some bean definitions. Since I have 3 datasources where everything is the same except for the port number, I created a parent bean so that the shared properties can be inherited. Then, I added the 3 bean definitions to represent the per-CustomerType DataSources:

<bean id="parentDataSource"
         class="org.springframework.jdbc.datasource.DriverManagerDataSource"
         abstract="true">
   <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
   <property name="username" value="sa"/>
</bean>
 
<bean id="goldDataSource" parent="parentDataSource">
   <property name="url" value="jdbc:hsqldb:hsql://localhost:${db.port.gold}/blog"/>
</bean>
 
<bean id="silverDataSource" parent="parentDataSource">
   <property name="url" value="jdbc:hsqldb:hsql://localhost:${db.port.silver}/blog"/>
</bean>
 
<bean id="bronzeDataSource" parent="parentDataSource">
   <property name="url" value="jdbc:hsqldb:hsql://localhost:${db.port.bronze}/blog"/>
</bean>
 
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location" value="classpath:/blog/datasource/db.properties"/>
</bean>

 

Notice that I added a PropertyPlaceholderConfigurer so that I could externalize the port numbers in a "db.properties" file, like so:

db.port.gold=9001
db.port.silver=9002
db.port.bronze=9003

 

Now things start to get interesting. I need to supply the "routing" DataSource to my Catalogso that it can dynamically get connections from the 3 different databases at runtime based on the current customer's type. As I mentioned, the AbstractRoutingDataSource can be rather simple to implement. Here is my implementation:

package blog.datasource;
 
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
 
public class CustomerRoutingDataSource extends AbstractRoutingDataSource {
 
   @Override
   protected Object determineCurrentLookupKey() {
      return CustomerContextHolder.getCustomerType();
   }
}

…and the CustomerContextHolder simply provides access to a thread-bound CustomerType. In reality, the 'context' would likely hold more information about the customer. Also note that if you are using Acegi, then you could retrieve some information from the userDetails. For this example, it's just the customer "type":

public class CustomerContextHolder {
 
   private static final ThreadLocal<CustomerType> contextHolder =
            new ThreadLocal<CustomerType>();
 
   public static void setCustomerType(CustomerType customerType) {
      Assert.notNull(customerType, "customerType cannot be null");
      contextHolder.set(customerType);
   }
 
   public static CustomerType getCustomerType() {
      return (CustomerType) contextHolder.get();
   }
 
   public static void clearCustomerType() {
      contextHolder.remove();
   }
}

 

Finally, I just need to configure the catalog and routing DataSource beans. As you can see, the "real" DataSource references are provided in a Map. If you provide Strings, they can be resolved as JNDI names (or any custom resolution strategy can be provided – see the JavaDoc). Also, I've simply set the 'bronzeDataSource' as the default:

<bean id="catalog" class="blog.datasource.Catalog">
   <property name="dataSource" ref="dataSource"/>
</bean>
 
<bean id="dataSource" class="blog.datasource.CustomerRoutingDataSource">
   <property name="targetDataSources">
      <map key-type="blog.datasource.CustomerType">
         <entry key="GOLD" value-ref="goldDataSource"/>
         <entry key="SILVER" value-ref="silverDataSource"/>
      </map>
   </property>
   <property name="defaultTargetDataSource" ref="bronzeDataSource"/>
</bean>

 

Of course I'd like to see this working, so I've created a simple test (extending one of Spring's integration test support classes). I added 3 items to the "gold" database, 2 items to the "silver" database, and only 1 item to the "bronze" database. This is the test:

public class CatalogTests extends AbstractDependencyInjectionSpringContextTests {
 
   private Catalog catalog;
 
   public void setCatalog(Catalog catalog) {
      this.catalog = catalog;
   }
 
   public void testDataSourceRouting() {
      CustomerContextHolder.setCustomerType(CustomerType.GOLD);
      List<Item> goldItems = catalog.getItems();
      assertEquals(3, goldItems.size());
      System.out.println("gold items: " + goldItems);
 
      CustomerContextHolder.setCustomerType(CustomerType.SILVER);
      List<Item> silverItems = catalog.getItems();
      assertEquals(2, silverItems.size());
      System.out.println("silver items: " + silverItems);
 
      CustomerContextHolder.clearCustomerType();
      List<Item> bronzeItems = catalog.getItems();
      assertEquals(1, bronzeItems.size());
      System.out.println("bronze items: " + bronzeItems);
   }
 
   protected String[] getConfigLocations() {
      return new String[] {"/blog/datasource/beans.xml"};
   }
}

…and rather than simply taking a screenshot of the green bar, you'll notice I've provided some console output – the results!:

gold items: [gold item #1 (250.0), gold item #2 (325.45), gold item #3 (55.6)]
silver items: [silver item #1 (25.0), silver item #2 (15.3)]
bronze items: [bronze item #1 (23.75)]

 

As you can see, the configuration is simple. Better still, the data-access code is not concerned with looking up different DataSources. For more information, consult the JavaDoc for AbstractRoutingDataSource.

阅读全文……

标签 : ,