/******************************************************************************* * Copyright (c) 2012 Kai Toedter and others. * * 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: * Kai Toedter - initial API and implementation ******************************************************************************/ package com.toedter.gwt.demo.contacts.server; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import com.toedter.gwt.demo.contacts.shared.Contact; public class VCardContactsRepository implements IContactsRepository { private final List<Contact> contacts; public VCardContactsRepository() { contacts = new ArrayList<Contact>(); try { for (File file : getContacts()) { Contact contact = readFromVCard(file.getAbsolutePath()); contact.setFileName(file.getAbsolutePath()); contacts.add(contact); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private File[] getContacts() throws Exception { String dir = getVCardsDir(); File directory = new File(dir); System.out.println("VCardContactsRepository loading vcards from" + directory.getCanonicalPath()); return directory.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(".vcf"); //$NON-NLS-1$ } }); } private String getVCardsDir() { String path = getClass().getResource("").getPath(); path = path.substring(1, path.indexOf("WEB-INF")) + "vcards"; return path; } @Override public void addContact(final Contact contact) { contacts.add(contact); saveContact(contact); } @Override public List<Contact> getAllContacts() { return contacts; } @Override public void removeContact(final Contact contact) { String fileName = contact.getFileName(); if (fileName != null && fileName.trim().length() > 0) { File file = new File(fileName); file.delete(); } contacts.remove(contact); } /** * Reads a Contact from a VCard. This method cannot parse a generic VCard, * but can only parse VCards created with Microsoft Outlook. The intention * is not to provide a generic VCard reader but an easy way to get contact * data (including pictures) in the repository. * * @param fileName * the vcard file * @return the created Contact */ public Contact readFromVCard(String fileName) { Contact contact = new Contact(); BufferedReader bufferedReader = null; String charSet = "Cp1252"; // parse the vCard try { InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(fileName), charSet); bufferedReader = new BufferedReader(inputStreamReader); String line; String value; while ((line = bufferedReader.readLine()) != null) { value = getVCardValue(line, "N"); if (value != null) { String[] result = value.split(";"); if (result.length > 0) { contact.setLastName(result[0]); } if (result.length > 1) { contact.setFirstName(result[1]); } if (result.length > 2) { contact.setMiddleName(result[2]); } if (result.length > 3) { contact.setTitle(result[3]); } continue; } value = getVCardValue(line, "TEL;WORK"); if (value != null) { contact.setPhone(value); continue; } value = getVCardValue(line, "TEL;CELL"); if (value != null) { contact.setMobile(value); continue; } value = getVCardValue(line, "ADR;WORK"); if (value != null) { String[] result = value.split(";"); if (result.length > 2) { contact.setStreet(result[2]); } if (result.length > 3) { contact.setCity(result[3]); } if (result.length > 4) { contact.setState(result[4]); } if (result.length > 5) { contact.setZip(result[5]); } if (result.length > 6) { contact.setCountry(result[6]); } continue; } value = getVCardValue(line, "EMAIL;PREF;INTERNET"); if (value != null) { contact.setEmail(value); continue; } value = getVCardValue(line, "URL;WORK"); if (value != null) { contact.setWebPage(value); continue; } value = getVCardValue(line, "ORG"); if (value != null) { contact.setCompany(value); continue; } value = getVCardValue(line, "TITLE"); if (value != null) { contact.setJobTitle(value); continue; } value = getVCardValue(line, "NOTE"); if (value != null) { contact.setNote(value); continue; } value = getVCardValue(line, "PHOTO;TYPE=JPEG;ENCODING=BASE64"); if (value != null) { line = bufferedReader.readLine(); StringBuilder builder = new StringBuilder(); while (line != null && line.length() > 0 && line.charAt(0) == ' ') { builder.append(line.trim()); line = bufferedReader.readLine(); } String jpegString = builder.toString(); String base64 = "data:image/png;base64," + jpegString; contact.setJpegString(base64); continue; } } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { if (bufferedReader != null) { bufferedReader.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return contact; } private String getVCardValue(String line, String token) { if (line.startsWith(token + ":") || line.startsWith(token + ";")) { String value = line.substring(line.indexOf(":") + 1); return value; } return null; } public void saveAsVCard(Contact contact, String fileName) throws IOException { String charSet = "CHARSET=" + Charset.defaultCharset().name(); String vCard = "BEGIN:VCARD" + "\nVERSION:2.1" + "\n" + getName(contact, charSet) + "FN;" + charSet + ":" + contact.getFirstName() + " " + contact.getLastName() + "\nORG;" + charSet + ":" + contact.getCompany() + "\nTITLE:" + contact.getJobTitle() + "\nNOTE:" + contact.getNote() + "\nTEL;WORK;VOICE:" + contact.getPhone() + "\nTEL;CELL;VOICE:" + contact.getMobile() + "\nADR;WORK;" + charSet + ":" + ";;" + contact.getStreet() + ";" + contact.getCity() + ";" + contact.getState() + ";" + contact.getZip() + ";" + contact.getCountry() + "\nURL;WORK:" + contact.getWebPage() + "\nEMAIL;PREF;INTERNET:" + contact.getEmail() + "\n"; if (!contact.getJpegString().equals("")) { vCard += "PHOTO;TYPE=JPEG;ENCODING=BASE64:\n " + contact.getJpegString() + "\n"; } vCard += "END:VCARD\n"; PrintWriter out = new PrintWriter(fileName, "Cp1252"); out.println(vCard); out.close(); } private String getName(Contact contact, String charSet) { StringBuilder builder = new StringBuilder(); builder.append("N;").append(charSet).append(':'); //$NON-NLS-1$ builder.append(contact.getLastName()).append(';'); builder.append(contact.getFirstName()).append(';'); builder.append(contact.getMiddleName()); String title = contact.getTitle(); if (title.length() != 0) { builder.append(';').append(title); } builder.append('\n'); return builder.toString(); } @Override public void saveContact(Contact contact) { try { String fileName = contact.getFileName(); if (fileName == null || fileName.trim().length() == 0) { String dir = getVCardsDir(); fileName = dir + "/" + contact.getFirstName() + " " + contact.getLastName() + ".vcf"; contact.setFileName(fileName); } else { Contact oldContact = getContactByFileName(fileName); if (oldContact != null) { contacts.remove(oldContact); } } contacts.add(contact); saveAsVCard(contact, fileName); } catch (IOException e) { System.err.println("could not save contact: " + contact + " to " + contact.getFileName()); } } public Contact getContactByFileName(String fileName) { for (Contact contact : contacts) { if (fileName.equals(contact.getFileName())) { return contact; } } return null; } }