рд╢реБрдн рджреЛрдкрд╣рд░, рд╕рд╛рдерд┐рдпреЛрдВ!
рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдЕрдкрдиреЗ
рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдерд╛, рдореИрдВ рдЖрдкрд╕реЗ Google рд╕рдВрдкрд░реНрдХ API рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдпрджрд┐ рдЖрдк Google рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЗрдВрдЬрди рдкрд░ Google рд╕рдВрдкрд░реНрдХ API рдХреЛ рдЬрд╛рд╡рд╛ рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рд╕реАрдЦрдиреЗ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдмрд┐рд▓реНрд▓реА рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИред
рдореЗрд░реЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ, рдореИрдВрдиреЗ рдЬрд╛рд╡рд╛ 1.8 рдХреЗ рд▓рд┐рдП Google рдПрдкреАрдЖрдИ рдХреНрд▓рд╛рдЗрдВрдЯ рд▓рд┐рд╡рд╛рд░реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ - рдЗрд╕ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдирд╡рд╛рдЪрд╛рд░ рд╣реИрдВ рдЬреЛ рдУрде рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛ рд╕рд░рд▓ рдмрдирд╛рддреЗ рд╣реИрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЕрдм рд╕рднреА рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХрд╛рд░реНрдп рдкреБрд╕реНрддрдХрд╛рд▓рдп рджреНрд╡рд╛рд░рд╛ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред
рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдПрдХ рд╡рд░реНрдЧ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рд╕рдВрдкрд░реНрдХ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдЧрд╛ред рдореИрдВрдиреЗ рдПрдХ рд╡рд░реНрдЧ рдмрдирд╛рдпрд╛ рдЬрд┐рд╕рдХрд╛ рдЙрдкрд╡рд░реНрдЧ рд╕рдВрдкрд░реНрдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рддрддреНрд╡реЛрдВ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИ - рдкрддреЗ, рдИ-рдореЗрд▓, рдЯреЗрд▓реАрдлреЛрди рдФрд░ рддрддреНрдХрд╛рд▓ рд╕рдВрджреЗрд╢рд╡рд╛рд╣рдХред
public class Contact implements Serializable { private static final String GDATA_URI = "http://schemas.google.com/g/2005#"; public static final String SOURCE_LABEL = "Source"; public class TypedSubElem implements Serializable{ protected String getURIPrefix(){ return Contact.GDATA_URI; } protected Map<String,String> getRelList(){ final Map<String,String> relList = Collections.unmodifiableMap(new HashMap<String,String>() {{put("home","."); put("other","."); put("work","."); }}); return relList; } @Key("@rel") protected String type = getURIPrefix()+"other"; @Key("@label") protected String label = null; public String getType(){ return (type == null)?null:type.substring(getURIPrefix().length()); } public String getLabel(){ return label; } public String getReadableType(){ String ret = getRelList().get(getType()); if(ret == null) ret = label; return ret; } public void setType(String type){ this.label = null; this.type = getURIPrefix()+(getRelList().containsKey(type)?type:"other"); } public void setLabel(String label){ this.type = null; this.label = label; } } public class FN implements Serializable { @Key("text()") public String text; } public class Content implements Serializable { @Key("text()") public String text; } public class Org extends TypedSubElem { @Key("gd:orgName") public String orgName; @Key("gd:orgTitle") public String orgTitle; @Key("gd:orgDepartment") public String orgDepartment; public void setWork(Boolean work) { setType(work?"work":"other"); } } public class Phone extends TypedSubElem { @Override protected Map<String,String> getRelList(){ final Map<String,String> relList = Collections.unmodifiableMap(new HashMap<String,String>() {{put("assistant",""); put("callback","."); put("car",""); put("company_main",". .")); put("fax",""); put("home","."); put("home_fax",". "); put("isdn","ISDN"); put("main","."); put("mobile","."); put("other","."); put("other_fax",". "); put("pager",""); put("radio",""); put("telex",""); put("tty_tdd","."); put("work","."); put("work_fax",". "); put("work_mob",". ."); put("work_pager",". "); }}); return relList; } @Key("text()") public String text; } public class Email extends TypedSubElem{ @Key("@address") public String address; } public class Address extends TypedSubElem{ @Key("gd:street") public String street; @Key("gd:city") public String city; @Key("gd:region") public String region; @Key("gd:postcode") public String postcode; @Key("gd:country") public String country; @Key("gd:formattedAddress") public String fullAddress; } public class Name extends SubElem{ @Key("gd:givenName") public String givenName; @Key("gd:additionalName") public String additionalName; @Key("gd:familyName") public String familyName; @Key("gd:namePrefix") public String namePrefix; @Key("gd:nameSuffix") public String nameSuffix; @Key("gd:fullName") private String fullName; } public class Link extends TypedSubElem { @Key("@href") public String url; @Override protected Map<String,String> getRelList(){ final Map<String,String> relList = Collections.unmodifiableMap(new HashMap<String,String>() {{put("home-page","."); put("blog",""); put("work","."); put("profile",""); put("other","."); }}); return relList; } @Override protected String getURIPrefix(){ return ""; } } public class IM extends Email { @Key("@protocol") public String protocol; @Override protected Map<String,String> getRelList(){ final Map<String,String> relList = Collections.unmodifiableMap(new HashMap<String,String>() {{put("home","."); put("other","."); put("netmeeting","NetMeeting"); put("work","."); }}); return relList; } protected Map<String,String> getProtoList(){ final Map<String,String> relList = Collections.unmodifiableMap(new HashMap<String,String>() {{put("AIM","AIM"); put("MSN","MSN"); put("YAHOO","Yahoo"); put("SKYPE","Skype"); put("QQ","QQ"); put("GOOGLE_TALK","GTalk"); put("ICQ","ICQ"); put("JABBER","Jabber"); }}); return relList; } public String getProtocol(){ return (protocol == null)?null:protocol.substring(protocol.lastIndexOf('#')+1); } public String getReadableProto(){ return getProtoList().get(getProtocol()); } public void setProtocol(String type){ this.protocol = (getProtoList().containsKey(type))?GDATA_URI+type:null; } } @Key("gContact:website") public List<Link> links = new ArrayList<Link>(); @Key public Content content; @Key("title") public FN fn; @Key("gd:phoneNumber") public List<Phone> phones = new ArrayList<Phone>(); @Key("gd:email") public List<Email> emails = new ArrayList<Email>(); @Key("gd:organization") public List<Org> orgs = new ArrayList<Org>(); @Key("gd:structuredPostalAddress") public List<Address> addresses = new ArrayList<Address>(); @Key("gd:im") public List<IM> IMs = new ArrayList<IM>(); @Key("gd:name") public Name name; }
рд╡рд░реНрдЧ рдФрд░ рдЙрд╕рдХреЗ рдЙрдкрд╡рд░реНрдЧреЛрдВ рдХреЛ рд╕реАрд░рд┐рдпрд▓-рдпреЛрдЧреНрдп рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ - рдпрд╣ Google API рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╕рдВрдкрд░реНрдХ рдХреЛ рд╕рд╣реА рдПрдЯрдо рдореЗрдВ рдмрджрд▓рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдХрд░реЗрдЧрд╛ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрди рд╕рднреА рдлрд╝реАрд▓реНрдбреНрд╕ рдХреЛ рд╕рд╣реЗрдЬрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рдиреНрд╣реЗрдВ рдПрдиреЛрдЯреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ
@тАМKey
- рдпрд╣ рд╣рдорд╛рд░реА рдХрдХреНрд╖рд╛ рдХреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рдкрддреНрд░рд╛рдЪрд╛рд░ рдФрд░ рдПрдЯрдо рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред
рд░рд┐рд▓реЗ рдФрд░ рд▓реЗрдмрд▓ рдлрд╝реАрд▓реНрдб рдПрдХ рдЕрд▓рдЧ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреЗ рд▓рд╛рдпрдХ рд╣реИрдВред rel рдПрдХ рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╕реВрдЪреА рд╕реЗ рд╕рдВрдкрд░реНрдХ рдЬрд╛рдирдХрд╛рд░реА рдХрд╛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЕрдВрдХрди рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдИ-рдореЗрд▓ рдХреЗ рд▓рд┐рдП рдпрд╣ рдПрдХ рд╕рдВрдХреЗрдд рд╣реЛрдЧрд╛ рдХрд┐ рдкрддрд╛ рдШрд░ рд╣реИ рдпрд╛ рдХрд╛рдоред "
APIas.google.com/g/2005# <view>" рдлрд╝реЙрд░реНрдо рдХрд╛ рдорд╛рди Google API рдХреЛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдареЗрда рдЪрд┐рд╣реНрдиреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕рдВрдкрд░реНрдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдПрдХ рдордирдорд╛рдирд╛ рдкрджрдирд╛рдо рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд▓реЗрдмрд▓ рдлрд╝реАрд▓реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред Google API рдХреЛ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдХреЛ рдЖрдмрд╛рджреА рджреА рдЬрд╛рдПрдЧреА - рдпрд╛ рддреЛ rel рдпрд╛ рд▓реЗрдмрд▓ред
рдЖрдк
рдпрд╣рд╛рдВ рд╕рдВрдкрд░реНрдХ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред
Google рдХреЛ рдПрдХ рд╕рдВрдкрд░реНрдХ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕рд░реНрд╡рд▓реЗрдЯ рдмрдирд╛рдПрдВ рдЬреЛ AbstractAppEngineAuthorizationCodeServlet рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИред рдпрд╣ рд╡рд░реНрдЧ рдЖрдкрдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХреЛрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдзрд┐рдХреГрдд рд╣реИ (Google рдЦрд╛рддреЛрдВ рдореЗрдВ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдпрд╛, рдпрджрд┐ рдЖрдк Google Apps рдЗрдВрдЬрди рдореЗрдВ рдЙрдкрдпреБрдХреНрдд рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ Federated Login рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ)ред рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдзрд┐рдХреГрдд рд╣реИ, рддреЛ рдЙрд╕рд╕реЗ рдкреВрдЫрд╛ рдЬрд╛рдПрдЧрд╛ (рдлрд┐рд░ рд╕реЗ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕рд░реНрд╡рд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ - рдЖрдкрдХреЛ Google рд╕рдВрдкрд░реНрдХреЛрдВ рдореЗрдВ рдЕрдкрдиреЗ рд╕рдВрдкрд░реНрдХреЛрдВ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рдпрдВ рдХреБрдЫ рднреА рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ)ред рдкреНрд░рд╛рдкреНрдд рдЯреЛрдХрди рдЯреЛрдХрди рд╕реНрдЯреЛрд░ рдореЗрдВ рднрд╡рд┐рд╖реНрдп рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рд╕рд╣реЗрдЬреЗ рдЬрд╛рдПрдВрдЧреЗ (рдореИрдВрдиреЗ AppEngineCredentialStore рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛)ред рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рд╕рдВрдкреВрд░реНрдг рдЕрдиреБрдХреНрд░рдо GoogleAuthorizationCodeFlow рдХреА рдЬрд┐рдореНрдореЗрджрд╛рд░реА рд╣реИред
import com.google.api.client.auth.oauth2.AuthorizationCodeFlow; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.appengine.auth.oauth2.AbstractAppEngineAuthorizationCodeServlet; import com.google.api.client.extensions.appengine.auth.oauth2.AppEngineCredentialStore; import com.google.api.client.extensions.appengine.http.urlfetch.UrlFetchTransport; import com.google.api.client.googleapis.GoogleHeaders; import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; import com.google.api.client.http.*; import com.google.api.client.http.xml.atom.AtomContent; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.jackson.JacksonFactory; import com.google.api.client.xml.XmlNamespaceDictionary; import java.io.IOException; import java.util.Collections; import java.util.ResourceBundle; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Action extends AbstractAppEngineAuthorizationCodeServlet { private static final String DEFAULT_BASE_URL = "https://www.google.com/m8/feeds/contacts/default/full"; public static final String SCOPE = "https://www.google.com/m8/feeds/"; public static final String CALLBACK_URI = "/action/google_contacts/oauth2callback"; private static final String APP_NAME = "< >"; public static final String CLIENT_ID = "< >"; public static final String CLIENT_SECRET = "<>"; private static final HttpTransport transport = new UrlFetchTransport(); private static final JsonFactory jsonFactory = new JacksonFactory(); static final XmlNamespaceDictionary DICTIONARY = new XmlNamespaceDictionary() .set("", "http://www.w3.org/2005/Atom") .set("gd", "http://schemas.google.com/g/2005") .set("gContact", "http://schemas.google.com/contact/2008"); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ Credential credential = getCredential(); Contact contact = (Contact) request.getSession().getAttribute("Contact"); if(credential != null && contact != null) { HttpRequestFactory requestFactory = transport.createRequestFactory(getCredential()); assert requestFactory!=null; HttpRequest req = requestFactory.buildPostRequest(new GenericUrl(DEFAULT_BASE_URL), null); GoogleHeaders headers = new GoogleHeaders(); headers.setApplicationName(APP_NAME); headers.setGDataVersion("3"); req.setHeaders(headers); AtomContent content = AtomContent.forEntry(DICTIONARY, contact); req.setContent(content); try{ HttpResponse resp = req.execute(); } catch (HttpResponseException e) { } } } @Override protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException { GenericUrl url = new GenericUrl(req.getRequestURL().toString()); url.setRawPath(CALLBACK_URI); return url.build(); } @Override protected AuthorizationCodeFlow initializeFlow() throws IOException { return new GoogleAuthorizationCodeFlow.Builder(new UrlFetchTransport(), new JacksonFactory(), CLIENT_ID, CLIENT_SECRET, Collections.singleton(SCOPE)).setCredentialStore( new AppEngineCredentialStore()).build(); } }
рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдЕрдиреБрд░реЛрдз рд╣реЗрдбрд░ рд╕реЗрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, Google рдПрдкреАрдЖрдИ рдХрд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рд╕рдВрдкрд░реНрдХ рд╕рдВрд╕реНрдХрд░рдг 2 рд╣реИ, рдЬреЛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕рдВрдкрд░реНрдХ рдХреЗ рд╕рдВрд░рдЪрд┐рдд рдирд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдПрдлрдПрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЕрдЧрд░ рдореИрдВ рдЧрд▓рдд рдирд╣реАрдВ рд╣реВрдВ, рддреЛ рдЗрд╕ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ IM рдбреЗрдЯрд╛ рд╕рд╣реЗрдЬрд╛ рдирд╣реАрдВ рдЧрдпрд╛ рд╣реИред
рдЖрдк
рдкреНрд░рд▓реЗрдЦрди рдкреГрд╖реНрда рдкрд░ рд╕рдВрдкрд░реНрдХ рдПрдкреАрдЖрдИ рдХреЗ рдЕрдиреНрдп рддрд░реАрдХреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред